@shbernal/ts-pptx 2.0.0 → 3.1.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/README.md +31 -2
- package/dist/{autopage-tmfjRzL4.js → autopage-QQyfRtoK.js} +4 -5
- package/dist/{autopage-tmfjRzL4.js.map → autopage-QQyfRtoK.js.map} +1 -1
- package/dist/browser.d.ts +14 -6
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +14 -6
- package/dist/browser.js.map +1 -1
- package/dist/{diagnostics-CQ0JWc9m.d.ts → diagnostics-PMINsVP6.d.ts} +97 -8
- package/dist/diagnostics-PMINsVP6.d.ts.map +1 -0
- package/dist/{enums-D3aF4QGb.d.ts → enums-CoXnxiCI.d.ts} +6 -5
- package/dist/{enums-D3aF4QGb.d.ts.map → enums-CoXnxiCI.d.ts.map} +1 -1
- package/dist/{errors-B22h8Qd0.d.ts → errors-BeUEkNWL.d.ts} +26 -4
- package/dist/errors-BeUEkNWL.d.ts.map +1 -0
- package/dist/{errors-DGE9zh3U.js → errors-Bvln0H-7.js} +21 -2
- package/dist/errors-Bvln0H-7.js.map +1 -0
- package/dist/{fit-BSWY0AYt.js → fit-DhMbQG5O.js} +0 -0
- package/dist/fit-DhMbQG5O.js.map +1 -0
- package/dist/{html-dom-BQLUntho.js → html-dom-DajBuobe.js} +20 -6
- package/dist/html-dom-DajBuobe.js.map +1 -0
- package/dist/html.d.ts +3 -3
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +7 -4
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +1 -1
- package/dist/inspect.js +4 -4
- package/dist/inspect.js.map +1 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +98 -2
- package/dist/math.js.map +1 -1
- package/dist/measure.d.ts +3 -3
- package/dist/measure.js +2 -2
- package/dist/node.d.ts +14 -6
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +13 -5
- package/dist/node.js.map +1 -1
- package/dist/package-CaOLXSNi.d.ts.map +1 -1
- package/dist/{pres-GU-jjBEx.d.ts → pres-BgvxhQ_m.d.ts} +3 -3
- package/dist/{pres-GU-jjBEx.d.ts.map → pres-BgvxhQ_m.d.ts.map} +1 -1
- package/dist/{presentation-MJe9WDi4.js → presentation-BP1B8PCF.js} +863 -343
- package/dist/presentation-BP1B8PCF.js.map +1 -0
- package/dist/{presentation-CVaTZw1V.d.ts → presentation-DyIRDKkp.d.ts} +742 -595
- package/dist/presentation-DyIRDKkp.d.ts.map +1 -0
- package/dist/{presentation-types-BVw0EknS.d.ts → presentation-types-Dj4riuDs.d.ts} +2 -2
- package/dist/{presentation-types-BVw0EknS.d.ts.map → presentation-types-Dj4riuDs.d.ts.map} +1 -1
- package/dist/read.d.ts +5 -5
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +3 -3
- package/dist/script.d.ts +2 -2
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +0 -0
- package/dist/script.js.map +1 -1
- package/dist/{shapes-CaOgR0i1.js → shapes-DMThLsZN.js} +689 -1032
- package/dist/shapes-DMThLsZN.js.map +1 -0
- package/dist/{slide-BBlElWr9.d.ts → slide-BRAtT8Dl.d.ts} +197 -22
- package/dist/slide-BRAtT8Dl.d.ts.map +1 -0
- package/dist/{image-size-C8uYE8GJ.js → st-enums-evQG2A7Z.js} +233 -2
- package/dist/st-enums-evQG2A7Z.js.map +1 -0
- package/dist/{text-B1ZrPEeK.js → text-B6PbMFih.js} +725 -319
- package/dist/text-B6PbMFih.js.map +1 -0
- package/dist/{units-B-JUKwCS.js → units-C7QM1KgH.js} +2 -2
- package/dist/{units-B-JUKwCS.js.map → units-C7QM1KgH.js.map} +1 -1
- package/dist/{units-internal-7JcMfYti.js → units-internal-CR8s8YQa.js} +4 -3
- package/dist/units-internal-CR8s8YQa.js.map +1 -0
- package/dist/zip.d.ts +2 -2
- package/dist/zip.js +1 -1
- package/dist/zip.js.map +1 -1
- package/package.json +40 -29
- package/skills/ts-pptx-upstream/SKILL.md +247 -0
- package/dist/diagnostics-CQ0JWc9m.d.ts.map +0 -1
- package/dist/errors-B22h8Qd0.d.ts.map +0 -1
- package/dist/errors-DGE9zh3U.js.map +0 -1
- package/dist/fit-BSWY0AYt.js.map +0 -1
- package/dist/html-dom-BQLUntho.js.map +0 -1
- package/dist/image-size-C8uYE8GJ.js.map +0 -1
- package/dist/presentation-CVaTZw1V.d.ts.map +0 -1
- package/dist/presentation-MJe9WDi4.js.map +0 -1
- package/dist/shapes-CaOgR0i1.js.map +0 -1
- package/dist/slide-BBlElWr9.d.ts.map +0 -1
- package/dist/text-B1ZrPEeK.js.map +0 -1
- package/dist/units-internal-7JcMfYti.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as warn, r as warnOnce } from "./diagnostics-DYQC7xLV.js";
|
|
2
|
-
import { n as InvalidOptionError, o as UnsupportedFeatureError, r as MediaError, t as InternalError } from "./errors-
|
|
3
|
-
import { a as FIXED_PCT_PER_PERCENT, d as emuToInches, g as pixelsToEmu, i as EMU_PER_POINT, l as STANDARD_LAYOUTS, m as inchesToEmu, r as EMU_PER_INCH, s as PERCENT_SCALE, t as ANGLE_UNITS_PER_DEGREE, v as ptToHundredths } from "./units-
|
|
4
|
-
import { $ as connectorPresetFor, C as DEF_PRES_LAYOUT_NAME, D as DEF_TEXT_GLOW, E as DEF_SLIDE_MARGIN_IN, F as PIECHART_COLORS, G as PlaceholderType, I as REGEX_HEX_COLOR, K as SchemeColor, L as SLDNUMFLDID, M as LAYOUT_IDX_SERIES_BASE, N as LETTERS, O as DEF_TEXT_SHADOW, Q as asChartType, R as XML_DECL, S as DEF_PRES_LAYOUT, T as DEF_SHAPE_SHADOW, Z as VALID_SHAPE_PRESETS, _ as DEF_CELL_BORDER, a as lineWidthToEmu, b as DEF_CHART_GRIDLINE, c as resolveTableColWidthsEmu, d as AXIS_ID_CATEGORY_PRIMARY, et as isChartExType, f as AXIS_ID_CATEGORY_SECONDARY, g as BARCHART_COLORS, h as AXIS_ID_VALUE_SECONDARY, i as inch2Emu, k as IMG_BROKEN, l as transparencyToAlpha, m as AXIS_ID_VALUE_PRIMARY, n as convertRotationDegrees, o as marginToEmu, p as AXIS_ID_SERIES_PRIMARY, r as getSmartParseNumber, s as opacityToAlpha, t as convertArcAngle, u as valToPts, v as DEF_CELL_MARGIN_IN, x as DEF_FONT_COLOR, y as DEF_CHART_BORDER } from "./units-internal-
|
|
5
|
-
import {
|
|
6
|
-
import { t as getSlidesForTableRows } from "./autopage-
|
|
7
|
-
import { _ as parseFontMetrics, m as FontMetricsRegistry, n as measureText, r as computeTableLayout, t as applyMeasuredFit } from "./fit-
|
|
2
|
+
import { n as InvalidOptionError, o as UnsupportedFeatureError, r as MediaError, t as InternalError } from "./errors-Bvln0H-7.js";
|
|
3
|
+
import { a as FIXED_PCT_PER_PERCENT, d as emuToInches, g as pixelsToEmu, i as EMU_PER_POINT, l as STANDARD_LAYOUTS, m as inchesToEmu, r as EMU_PER_INCH, s as PERCENT_SCALE, t as ANGLE_UNITS_PER_DEGREE, v as ptToHundredths } from "./units-C7QM1KgH.js";
|
|
4
|
+
import { $ as connectorPresetFor, C as DEF_PRES_LAYOUT_NAME, D as DEF_TEXT_GLOW, E as DEF_SLIDE_MARGIN_IN, F as PIECHART_COLORS, G as PlaceholderType, I as REGEX_HEX_COLOR, K as SchemeColor, L as SLDNUMFLDID, M as LAYOUT_IDX_SERIES_BASE, N as LETTERS, O as DEF_TEXT_SHADOW, Q as asChartType, R as XML_DECL, S as DEF_PRES_LAYOUT, T as DEF_SHAPE_SHADOW, Z as VALID_SHAPE_PRESETS, _ as DEF_CELL_BORDER, a as lineWidthToEmu, b as DEF_CHART_GRIDLINE, c as resolveTableColWidthsEmu, d as AXIS_ID_CATEGORY_PRIMARY, et as isChartExType, f as AXIS_ID_CATEGORY_SECONDARY, g as BARCHART_COLORS, h as AXIS_ID_VALUE_SECONDARY, i as inch2Emu, k as IMG_BROKEN, l as transparencyToAlpha, m as AXIS_ID_VALUE_PRIMARY, n as convertRotationDegrees, o as marginToEmu, p as AXIS_ID_SERIES_PRIMARY, r as getSmartParseNumber, s as opacityToAlpha, t as convertArcAngle, u as valToPts, v as DEF_CELL_MARGIN_IN, x as DEF_FONT_COLOR, y as DEF_CHART_BORDER } from "./units-internal-CR8s8YQa.js";
|
|
5
|
+
import { E as svgMarkupToDataUri, S as getImageSizeFromBase64, T as decodeBase64ToBytes, a as PRESET_MATERIALS, g as PACKAGE_REL_NS, h as OFFICE_REL, i as PRESET_LINE_DASHES, n as LIGHT_RIGS, r as LIGHT_RIG_DIRECTIONS, s as TEXT_HORZ_OVERFLOW, t as BEVEL_PRESETS, u as checkEnumOrWarn, x as fitSrcRectPercents } from "./st-enums-evQG2A7Z.js";
|
|
6
|
+
import { t as getSlidesForTableRows } from "./autopage-QQyfRtoK.js";
|
|
7
|
+
import { _ as parseFontMetrics, m as FontMetricsRegistry, n as measureText, r as computeTableLayout, t as applyMeasuredFit } from "./fit-DhMbQG5O.js";
|
|
8
8
|
import { a as flattenEmbeddedFaces, i as FONT_REL_TYPE, n as FONT_DATA_CONTENT_TYPE, o as serializeEmbeddedFontLst, r as FONT_DATA_EXTENSION, t as EMBEDDED_FONT_SLOTS } from "./embedded-fonts-MaynAHa9.js";
|
|
9
9
|
import { ZipWriter } from "./zip.js";
|
|
10
10
|
//#region src/media/content-type.ts
|
|
@@ -1326,7 +1326,7 @@ function addImageDefinition(target, opt) {
|
|
|
1326
1326
|
let defWidth = intWidth;
|
|
1327
1327
|
let defHeight = intHeight;
|
|
1328
1328
|
let szAuto;
|
|
1329
|
-
if ((!intWidth || !intHeight) && strImgExtn
|
|
1329
|
+
if ((!intWidth || !intHeight) && !(strImgExtn === "svg" && !intWidth && !intHeight)) {
|
|
1330
1330
|
const natural = strImageData ? getImageSizeFromBase64(strImageData) : null;
|
|
1331
1331
|
if (natural) {
|
|
1332
1332
|
if (!intWidth && !intHeight) {
|
|
@@ -1961,23 +1961,6 @@ function addMediaDefinition(target, opt) {
|
|
|
1961
1961
|
target._slideObjects.push(slideData);
|
|
1962
1962
|
}
|
|
1963
1963
|
//#endregion
|
|
1964
|
-
//#region src/gen/define/notes.ts
|
|
1965
|
-
/**
|
|
1966
|
-
* Adds Notes to a slide.
|
|
1967
|
-
* @param {PresSlideInternal} `target` slide object
|
|
1968
|
-
* @param {string | NotesProps | NotesProps[]} `notes` plain text, or rich runs (inline formatting / hyperlinks)
|
|
1969
|
-
*/
|
|
1970
|
-
function addNotesDefinition(target, notes) {
|
|
1971
|
-
const runs = typeof notes === "string" ? [{ text: notes }] : (Array.isArray(notes) ? notes : [notes]).map((run) => ({
|
|
1972
|
-
text: run.text,
|
|
1973
|
-
options: run.options
|
|
1974
|
-
}));
|
|
1975
|
-
target._slideObjects.push({
|
|
1976
|
-
_type: "notes",
|
|
1977
|
-
text: runs
|
|
1978
|
-
});
|
|
1979
|
-
}
|
|
1980
|
-
//#endregion
|
|
1981
1964
|
//#region src/gen/define/preview-image.ts
|
|
1982
1965
|
/**
|
|
1983
1966
|
* Register a preview/cover image as a slide media rel (deduped like `addImage`) and return its rId.
|
|
@@ -2010,11 +1993,140 @@ function registerPreviewImage(target, cover) {
|
|
|
2010
1993
|
return rId;
|
|
2011
1994
|
}
|
|
2012
1995
|
//#endregion
|
|
1996
|
+
//#region src/gen/define/model3d.ts
|
|
1997
|
+
/** OPC content type for a glTF binary, as PowerPoint spells it in `[Content_Types].xml`. */
|
|
1998
|
+
const GLB_CONTENT_TYPE = "model/gltf.binary";
|
|
1999
|
+
/** `.rels` `Type` URI for the embedded 3D model part. Note `2017/06` — not the namespace's `2017`. */
|
|
2000
|
+
const MODEL3D_REL_TYPE = "http://schemas.microsoft.com/office/2017/06/relationships/model3d";
|
|
2001
|
+
/** Fixed-point denominator for `am3d` linear values: `am3d:up@dy="36000000"` is the unit vector. */
|
|
2002
|
+
const AM3D_UNIT = 36e6;
|
|
2003
|
+
/** Denominator of every `am3d` rational (`meterPerModelUnit`, `scale`, `illuminance`, `intensity`). */
|
|
2004
|
+
const AM3D_RATIO_DEN = 1e6;
|
|
2005
|
+
/** `am3d:perspective@fov` is in 60000ths of a degree, like every other DrawingML angle. */
|
|
2006
|
+
const FOV_PER_DEGREE = 6e4;
|
|
2007
|
+
/**
|
|
2008
|
+
* The camera PowerPoint wrote for the 2×2×2 cube fixture, in caller units (metres / degrees).
|
|
2009
|
+
* `z` is `sqrt(3)/2 / sin(22.5°)` — the bounding sphere of a 1-metre cube framed at a 45° fov.
|
|
2010
|
+
*/
|
|
2011
|
+
const DEFAULT_CAMERA = {
|
|
2012
|
+
pos: {
|
|
2013
|
+
x: 0,
|
|
2014
|
+
y: 0,
|
|
2015
|
+
z: 2.2630334
|
|
2016
|
+
},
|
|
2017
|
+
lookAt: {
|
|
2018
|
+
x: 0,
|
|
2019
|
+
y: 0,
|
|
2020
|
+
z: 0
|
|
2021
|
+
},
|
|
2022
|
+
up: {
|
|
2023
|
+
x: 0,
|
|
2024
|
+
y: 1,
|
|
2025
|
+
z: 0
|
|
2026
|
+
},
|
|
2027
|
+
fov: 45
|
|
2028
|
+
};
|
|
2029
|
+
/** `am3d:meterPerModelUnit` for the cube fixture: 1 / (its 2-unit largest extent). */
|
|
2030
|
+
const DEFAULT_METER_PER_MODEL_UNIT = .5;
|
|
2031
|
+
/** Reject a non-finite camera component rather than letting `NaN` reach the XML as `"NaN"`. */
|
|
2032
|
+
function toAm3dUnits(point, fallback, label) {
|
|
2033
|
+
const src = point ?? fallback;
|
|
2034
|
+
for (const axis of [
|
|
2035
|
+
"x",
|
|
2036
|
+
"y",
|
|
2037
|
+
"z"
|
|
2038
|
+
]) if (!Number.isFinite(src[axis])) throw new InvalidOptionError("model3d/invalid-camera", `addModel3d(): camera.${label}.${axis} must be a finite number, got ${String(src[axis])}.`);
|
|
2039
|
+
return {
|
|
2040
|
+
x: Math.round(src.x * AM3D_UNIT),
|
|
2041
|
+
y: Math.round(src.y * AM3D_UNIT),
|
|
2042
|
+
z: Math.round(src.z * AM3D_UNIT)
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
/** Resolve `camera` + `meterPerModelUnit` into the wire units {@link Model3dInternal} carries. */
|
|
2046
|
+
function resolveCamera(camera, meterPerModelUnit) {
|
|
2047
|
+
const fovDeg = camera?.fov ?? DEFAULT_CAMERA.fov;
|
|
2048
|
+
if (!Number.isFinite(fovDeg) || fovDeg <= 0 || fovDeg >= 180) throw new InvalidOptionError("model3d/invalid-fov", `addModel3d(): camera.fov must be greater than 0 and less than 180 degrees, got ${String(fovDeg)}.`);
|
|
2049
|
+
const scale = meterPerModelUnit ?? DEFAULT_METER_PER_MODEL_UNIT;
|
|
2050
|
+
if (!Number.isFinite(scale) || scale <= 0) throw new InvalidOptionError("model3d/invalid-scale", `addModel3d(): meterPerModelUnit must be a finite number greater than 0, got ${String(scale)}.`);
|
|
2051
|
+
const up = toAm3dUnits(camera?.up, DEFAULT_CAMERA.up, "up");
|
|
2052
|
+
return {
|
|
2053
|
+
pos: toAm3dUnits(camera?.pos, DEFAULT_CAMERA.pos, "pos"),
|
|
2054
|
+
lookAt: toAm3dUnits(camera?.lookAt, DEFAULT_CAMERA.lookAt, "lookAt"),
|
|
2055
|
+
up: {
|
|
2056
|
+
dx: up.x,
|
|
2057
|
+
dy: up.y,
|
|
2058
|
+
dz: up.z
|
|
2059
|
+
},
|
|
2060
|
+
fov: Math.round(fovDeg * FOV_PER_DEGREE),
|
|
2061
|
+
meterPerModelUnitN: Math.round(scale * AM3D_RATIO_DEN)
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
/**
|
|
2065
|
+
* Adds an embedded 3D model to a slide definition.
|
|
2066
|
+
* @param {PresSlideInternal} target - slide the model will be added to
|
|
2067
|
+
* @param {Model3dProps} opt - 3D model options
|
|
2068
|
+
*/
|
|
2069
|
+
function addModel3dDefinition(target, opt) {
|
|
2070
|
+
const strData = opt.data || "";
|
|
2071
|
+
const strPath = opt.path || "";
|
|
2072
|
+
if (!strPath && !strData) throw new InvalidOptionError("model3d/missing-source", "addModel3d(): either `data` or `path` are required!");
|
|
2073
|
+
const camera = resolveCamera(opt.camera, opt.meterPerModelUnit);
|
|
2074
|
+
const nameIdx = nextObjectNameIdx(target, "model3d");
|
|
2075
|
+
const objectName = opt.objectName ? encodeXmlAttrValue(validateObjectName(opt.objectName, "model3d")) : `3D Model ${nameIdx + 1}`;
|
|
2076
|
+
const modelRid = getNewRelId(target);
|
|
2077
|
+
const mediaSlideKey = target._slideNum == null ? "sm" : target._slideNum >= 1e3 ? `sl-${target._slideNum}` : target._slideNum;
|
|
2078
|
+
target._relsMedia.push({
|
|
2079
|
+
path: strPath || "preencoded.glb",
|
|
2080
|
+
type: GLB_CONTENT_TYPE,
|
|
2081
|
+
extn: "glb",
|
|
2082
|
+
data: strData,
|
|
2083
|
+
rId: modelRid,
|
|
2084
|
+
model3dRelType: MODEL3D_REL_TYPE,
|
|
2085
|
+
Target: `../media/model3d-${mediaSlideKey}-${target._relsMedia.length + 1}.glb`
|
|
2086
|
+
});
|
|
2087
|
+
if (!opt.preview?.path && !opt.preview?.data) warn("model3d/preview-missing", "addModel3d(): no `preview` image supplied, so a gray placeholder is embedded. PowerPoint 2019+ draws the live model over it, but thumbnails, PDF export and older viewers show the placeholder.");
|
|
2088
|
+
const previewRid = registerPreviewImage(target, opt.preview);
|
|
2089
|
+
const slideData = {
|
|
2090
|
+
_type: "model3d",
|
|
2091
|
+
options: {
|
|
2092
|
+
x: opt.x ?? 0,
|
|
2093
|
+
y: opt.y ?? 0,
|
|
2094
|
+
w: opt.w ?? 4,
|
|
2095
|
+
h: opt.h ?? 3,
|
|
2096
|
+
objectName,
|
|
2097
|
+
...opt.altText ? { altText: opt.altText } : {}
|
|
2098
|
+
},
|
|
2099
|
+
model3d: {
|
|
2100
|
+
modelRid,
|
|
2101
|
+
previewRid,
|
|
2102
|
+
...camera
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
target._slideObjects.push(slideData);
|
|
2106
|
+
}
|
|
2107
|
+
//#endregion
|
|
2108
|
+
//#region src/gen/define/notes.ts
|
|
2109
|
+
/**
|
|
2110
|
+
* Adds Notes to a slide.
|
|
2111
|
+
* @param {PresSlideInternal} `target` slide object
|
|
2112
|
+
* @param {string | NotesProps | NotesProps[]} `notes` plain text, or rich runs (inline formatting / hyperlinks)
|
|
2113
|
+
*/
|
|
2114
|
+
function addNotesDefinition(target, notes) {
|
|
2115
|
+
const runs = typeof notes === "string" ? [{ text: notes }] : (Array.isArray(notes) ? notes : [notes]).map((run) => ({
|
|
2116
|
+
text: run.text,
|
|
2117
|
+
options: run.options
|
|
2118
|
+
}));
|
|
2119
|
+
target._slideObjects.push({
|
|
2120
|
+
_type: "notes",
|
|
2121
|
+
text: runs
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2124
|
+
//#endregion
|
|
2013
2125
|
//#region src/gen/define/ole.ts
|
|
2014
2126
|
/** Rel type for an embedded OPC package (an Office file, itself a zip). */
|
|
2015
|
-
const PACKAGE_REL = "
|
|
2127
|
+
const PACKAGE_REL = OFFICE_REL + "package";
|
|
2016
2128
|
/** Rel type for a generic OLE-server blob — a compound-file `.bin` (ECMA-376 Part 1 §15.2.10). */
|
|
2017
|
-
const OLE_OBJECT_REL = "
|
|
2129
|
+
const OLE_OBJECT_REL = OFFICE_REL + "oleObject";
|
|
2018
2130
|
/**
|
|
2019
2131
|
* Embeddable payload formats, keyed by file extension. The six Office extensions are OPC packages
|
|
2020
2132
|
* and keep their own extension in `ppt/embeddings/`; everything else is embedded as a generic OLE
|
|
@@ -2220,7 +2332,7 @@ function applyTableHeaderColumnSugar(tableRows, opt) {
|
|
|
2220
2332
|
options: {}
|
|
2221
2333
|
} : {
|
|
2222
2334
|
...cell,
|
|
2223
|
-
options: { ...cell.options
|
|
2335
|
+
options: { ...cell.options }
|
|
2224
2336
|
};
|
|
2225
2337
|
const colDef = cols ? cols[colCursor] : void 0;
|
|
2226
2338
|
colCursor += cellObj.options?.colspan || 1;
|
|
@@ -2805,6 +2917,24 @@ var SlideBuilder = class {
|
|
|
2805
2917
|
return this;
|
|
2806
2918
|
}
|
|
2807
2919
|
/**
|
|
2920
|
+
* Add an embedded 3D model (PowerPoint's Insert ▸ 3D Models) to the Slide.
|
|
2921
|
+
*
|
|
2922
|
+
* The `.glb` bytes ship inside the `.pptx`, so PowerPoint 2019+ renders the model live and lets
|
|
2923
|
+
* the viewer orbit it. Everything else — older PowerPoint, thumbnails, PDF export — draws the
|
|
2924
|
+
* `preview` picture instead; without one a neutral gray placeholder is embedded.
|
|
2925
|
+
*
|
|
2926
|
+
* Most models also need `meterPerModelUnit`: ts-pptx does not parse the `.glb`, so it cannot
|
|
2927
|
+
* measure the bounding box PowerPoint would have scaled the scene by. Set it to
|
|
2928
|
+
* `1 / <largest bounding-box dimension in model units>`.
|
|
2929
|
+
* @param {Model3dProps} options - 3D model options
|
|
2930
|
+
* @return {SlideBuilder} this Slide
|
|
2931
|
+
* @example slide.addModel3d({ path: 'engine.glb', preview: { path: 'engine.png' }, x: 1, y: 1, w: 6, h: 4 })
|
|
2932
|
+
*/
|
|
2933
|
+
addModel3d(options) {
|
|
2934
|
+
addModel3dDefinition(this, options);
|
|
2935
|
+
return this;
|
|
2936
|
+
}
|
|
2937
|
+
/**
|
|
2808
2938
|
* Add speaker notes to Slide
|
|
2809
2939
|
* @param {string | NotesProps | NotesProps[]} notes - notes text, or rich runs with inline
|
|
2810
2940
|
* formatting / hyperlinks. A plain string is the single-run case; pass run objects to add
|
|
@@ -3075,6 +3205,9 @@ function genXmlColorSelection(props) {
|
|
|
3075
3205
|
internalElements += alphaFromTransparency(props.transparency);
|
|
3076
3206
|
}
|
|
3077
3207
|
switch (fillType) {
|
|
3208
|
+
case "none":
|
|
3209
|
+
outText += voidEl("a:noFill");
|
|
3210
|
+
break;
|
|
3078
3211
|
case "solid":
|
|
3079
3212
|
outText += el("a:solidFill", null, raw(createColorElement(colorVal, internalElements)));
|
|
3080
3213
|
break;
|
|
@@ -3104,23 +3237,6 @@ const BORDER_KEYS = [
|
|
|
3104
3237
|
"cap"
|
|
3105
3238
|
];
|
|
3106
3239
|
/**
|
|
3107
|
-
* The `ST_PresetLineDashVal` tokens `BorderProps.dashType` accepts — the same set
|
|
3108
|
-
* `ShapeLineProps.dashType` does, so a caller who knows one knows the other.
|
|
3109
|
-
*/
|
|
3110
|
-
const BORDER_DASH_VALUES = [
|
|
3111
|
-
"solid",
|
|
3112
|
-
"dot",
|
|
3113
|
-
"dash",
|
|
3114
|
-
"lgDash",
|
|
3115
|
-
"dashDot",
|
|
3116
|
-
"lgDashDot",
|
|
3117
|
-
"lgDashDotDot",
|
|
3118
|
-
"sysDash",
|
|
3119
|
-
"sysDot",
|
|
3120
|
-
"sysDashDot",
|
|
3121
|
-
"sysDashDotDot"
|
|
3122
|
-
];
|
|
3123
|
-
/**
|
|
3124
3240
|
* Resolve the `a:prstDash/@val` a border should emit.
|
|
3125
3241
|
*
|
|
3126
3242
|
* `BorderProps.type` is a three-way switch, so on its own it can only say "dashed" and
|
|
@@ -3136,14 +3252,7 @@ const BORDER_DASH_VALUES = [
|
|
|
3136
3252
|
*/
|
|
3137
3253
|
function resolveBorderDash(border) {
|
|
3138
3254
|
const fromType = border.type === "dash" ? "sysDash" : "solid";
|
|
3139
|
-
|
|
3140
|
-
if (dash === void 0 || dash === null) return fromType;
|
|
3141
|
-
if (BORDER_DASH_VALUES.includes(dash)) return dash;
|
|
3142
|
-
warnOnce("border/invalid-dash-type", `border: dashType \`${String(dash)}\` is not a valid value and is ignored — use one of ${BORDER_DASH_VALUES.join(", ")}.`, {
|
|
3143
|
-
received: dash,
|
|
3144
|
-
valid: BORDER_DASH_VALUES
|
|
3145
|
-
});
|
|
3146
|
-
return fromType;
|
|
3255
|
+
return checkEnumOrWarn(border.dashType, PRESET_LINE_DASHES, "border/invalid-dash-type", "border: dashType") ?? fromType;
|
|
3147
3256
|
}
|
|
3148
3257
|
/**
|
|
3149
3258
|
* Report an authored key that is not part of `BorderProps`, which the library would
|
|
@@ -3585,7 +3694,34 @@ function makeSeriesDataPointsXml(chartType, obj, opts, varyColors) {
|
|
|
3585
3694
|
* gridlines, optional axis title -- but PowerPoint requires the child elements in a
|
|
3586
3695
|
* fixed order that differs per axis, so they stay as three separate builders rather
|
|
3587
3696
|
* than one parameterized one. Called by {@link ./chart-xml}'s axis region.
|
|
3588
|
-
|
|
3697
|
+
*
|
|
3698
|
+
* Sub-blocks are shared where they can be shared *exactly*: {@link axisLineSpPr} covers
|
|
3699
|
+
* `<c:spPr>`, which differs between the three only by indent width. `<c:txPr>` is
|
|
3700
|
+
* deliberately left duplicated — its inherited indentation is irregular *within* each copy
|
|
3701
|
+
* as well as between them (the category axis closes `</a:defRPr>` at three spaces, the value
|
|
3702
|
+
* axis at six), so parameterising it would take about as many indent arguments as it has
|
|
3703
|
+
* lines and would hide the quirks rather than share the structure.
|
|
3704
|
+
*/
|
|
3705
|
+
/**
|
|
3706
|
+
* The `<c:spPr>` axis-line block, identical in shape on all three axes.
|
|
3707
|
+
*
|
|
3708
|
+
* The only thing that differed between the three copies was how far each was indented — two
|
|
3709
|
+
* spaces on the category and series axes, one on the value axis — and that irregularity is
|
|
3710
|
+
* inherited, not meaningful. It is reproduced here rather than normalised because inter-element
|
|
3711
|
+
* whitespace being inert does not make changing it free: byte-identity is the gate that proves
|
|
3712
|
+
* an emitter refactor changed nothing, and it cannot tell a "harmless" whitespace edit from a
|
|
3713
|
+
* real one. `indent` keeps the quirk visible at the call site.
|
|
3714
|
+
* @param {number} indent - leading spaces on the `<c:spPr>` line; children step out by 2 and 4
|
|
3715
|
+
* @param {number} widthEmu - line width for `a:ln@w`
|
|
3716
|
+
* @param {boolean | undefined} show - false emits `<a:noFill/>` instead of a colour
|
|
3717
|
+
* @param {string | undefined} color - line colour, defaulting to {@link DEF_GRIDLINE_COLOR}
|
|
3718
|
+
* @param {string} dash - `a:prstDash@val`
|
|
3719
|
+
* @return {string} XML `<c:spPr>`
|
|
3720
|
+
*/
|
|
3721
|
+
function axisLineSpPr(indent, widthEmu, show, color, dash) {
|
|
3722
|
+
const at = (extra) => " ".repeat(indent + extra);
|
|
3723
|
+
return `${at(0)}<c:spPr>${at(2)}<a:ln w="${widthEmu}" cap="flat">` + (!show ? "<a:noFill/>" : genXmlColorSelection(color || DEF_GRIDLINE_COLOR)) + `${at(4)}<a:prstDash val="${dash}"/>${at(4)}<a:round/>${at(2)}</a:ln>${at(0)}</c:spPr>`;
|
|
3724
|
+
}
|
|
3589
3725
|
function makeCatAxis(opts, axisId, valAxisId) {
|
|
3590
3726
|
let strXml = "";
|
|
3591
3727
|
const usesValueAxisForCategories = opts._type === "scatter" || opts._type === "bubble" || opts._type === "bubble3D";
|
|
@@ -3594,7 +3730,7 @@ function makeCatAxis(opts, axisId, valAxisId) {
|
|
|
3594
3730
|
else strXml += "<c:" + (opts.catLabelFormatCode ? "dateAx" : "catAx") + ">";
|
|
3595
3731
|
strXml += " <c:axId val=\"" + axisId + "\"/>";
|
|
3596
3732
|
strXml += " <c:scaling>";
|
|
3597
|
-
strXml += "<c:orientation val=\"" + (opts.catAxisOrientation ||
|
|
3733
|
+
strXml += "<c:orientation val=\"" + (opts.catAxisOrientation || "minMax") + "\"/>";
|
|
3598
3734
|
if (opts.catAxisMaxVal || opts.catAxisMaxVal === 0) strXml += `<c:max val="${opts.catAxisMaxVal}"/>`;
|
|
3599
3735
|
if (opts.catAxisMinVal || opts.catAxisMinVal === 0) strXml += `<c:min val="${opts.catAxisMinVal}"/>`;
|
|
3600
3736
|
strXml += "</c:scaling>";
|
|
@@ -3627,13 +3763,7 @@ function makeCatAxis(opts, axisId, valAxisId) {
|
|
|
3627
3763
|
strXml += " <c:minorTickMark val=\"" + (opts.catAxisMinorTickMark || "none") + "\"/>";
|
|
3628
3764
|
strXml += " <c:tickLblPos val=\"" + (opts.catAxisLabelPos || (opts.barDir === "col" ? "low" : "nextTo")) + "\"/>";
|
|
3629
3765
|
}
|
|
3630
|
-
strXml +=
|
|
3631
|
-
strXml += ` <a:ln w="${opts.catAxisLineSize ? valToPts(opts.catAxisLineSize) : EMU_PER_POINT}" cap="flat">`;
|
|
3632
|
-
strXml += !opts.catAxisLineShow ? "<a:noFill/>" : genXmlColorSelection(opts.catAxisLineColor || DEF_GRIDLINE_COLOR);
|
|
3633
|
-
strXml += " <a:prstDash val=\"" + (opts.catAxisLineStyle || "solid") + "\"/>";
|
|
3634
|
-
strXml += " <a:round/>";
|
|
3635
|
-
strXml += " </a:ln>";
|
|
3636
|
-
strXml += " </c:spPr>";
|
|
3766
|
+
strXml += axisLineSpPr(2, opts.catAxisLineSize ? valToPts(opts.catAxisLineSize) : EMU_PER_POINT, opts.catAxisLineShow, opts.catAxisLineColor, opts.catAxisLineStyle || "solid");
|
|
3637
3767
|
strXml += " <c:txPr>";
|
|
3638
3768
|
if (opts.catAxisLabelRotate) strXml += `<a:bodyPr rot="${convertRotationDegrees(opts.catAxisLabelRotate)}"/>`;
|
|
3639
3769
|
else strXml += "<a:bodyPr/>";
|
|
@@ -3697,7 +3827,7 @@ function makeValAxis(opts, valAxisId) {
|
|
|
3697
3827
|
strXml += " <c:axId val=\"" + valAxisId + "\"/>";
|
|
3698
3828
|
strXml += " <c:scaling>";
|
|
3699
3829
|
if (opts.valAxisLogScaleBase) strXml += `<c:logBase val="${opts.valAxisLogScaleBase}"/>`;
|
|
3700
|
-
strXml += "<c:orientation val=\"" + (opts.valAxisOrientation ||
|
|
3830
|
+
strXml += "<c:orientation val=\"" + (opts.valAxisOrientation || "minMax") + "\"/>";
|
|
3701
3831
|
if (opts.valAxisMaxVal || opts.valAxisMaxVal === 0) strXml += `<c:max val="${opts.valAxisMaxVal}"/>`;
|
|
3702
3832
|
if (opts.valAxisMinVal || opts.valAxisMinVal === 0) strXml += `<c:min val="${opts.valAxisMinVal}"/>`;
|
|
3703
3833
|
strXml += " </c:scaling>";
|
|
@@ -3724,13 +3854,7 @@ function makeValAxis(opts, valAxisId) {
|
|
|
3724
3854
|
strXml += " <c:minorTickMark val=\"" + (opts.valAxisMinorTickMark || "none") + "\"/>";
|
|
3725
3855
|
strXml += " <c:tickLblPos val=\"" + (opts.valAxisLabelPos || (opts.barDir === "col" ? "nextTo" : "low")) + "\"/>";
|
|
3726
3856
|
}
|
|
3727
|
-
strXml +=
|
|
3728
|
-
strXml += ` <a:ln w="${opts.valAxisLineSize ? valToPts(opts.valAxisLineSize) : EMU_PER_POINT}" cap="flat">`;
|
|
3729
|
-
strXml += !opts.valAxisLineShow ? "<a:noFill/>" : genXmlColorSelection(opts.valAxisLineColor || DEF_GRIDLINE_COLOR);
|
|
3730
|
-
strXml += " <a:prstDash val=\"" + (opts.valAxisLineStyle || "solid") + "\"/>";
|
|
3731
|
-
strXml += " <a:round/>";
|
|
3732
|
-
strXml += " </a:ln>";
|
|
3733
|
-
strXml += " </c:spPr>";
|
|
3857
|
+
strXml += axisLineSpPr(1, opts.valAxisLineSize ? valToPts(opts.valAxisLineSize) : EMU_PER_POINT, opts.valAxisLineShow, opts.valAxisLineColor, opts.valAxisLineStyle || "solid");
|
|
3734
3858
|
strXml += " <c:txPr>";
|
|
3735
3859
|
strXml += ` <a:bodyPr${opts.valAxisLabelRotate ? " rot=\"" + convertRotationDegrees(opts.valAxisLabelRotate).toString() + "\"" : ""}/>`;
|
|
3736
3860
|
strXml += " <a:lstStyle/>";
|
|
@@ -3765,7 +3889,7 @@ function makeSerAxis(opts, axisId, valAxisId) {
|
|
|
3765
3889
|
let strXml = "";
|
|
3766
3890
|
strXml += "<c:serAx>";
|
|
3767
3891
|
strXml += " <c:axId val=\"" + axisId + "\"/>";
|
|
3768
|
-
strXml += " <c:scaling><c:orientation val=\"" + (opts.serAxisOrientation ||
|
|
3892
|
+
strXml += " <c:scaling><c:orientation val=\"" + (opts.serAxisOrientation || "minMax") + "\"/></c:scaling>";
|
|
3769
3893
|
strXml += " <c:delete val=\"" + (opts.serAxisHidden ? "1" : "0") + "\"/>";
|
|
3770
3894
|
strXml += " <c:axPos val=\"" + (opts.barDir === "col" ? "b" : "l") + "\"/>";
|
|
3771
3895
|
strXml += opts.serGridLine && opts.serGridLine.style !== "none" ? createGridLineElement(opts.serGridLine) : "";
|
|
@@ -3783,13 +3907,7 @@ function makeSerAxis(opts, axisId, valAxisId) {
|
|
|
3783
3907
|
strXml += " <c:majorTickMark val=\"out\"/>";
|
|
3784
3908
|
strXml += " <c:minorTickMark val=\"none\"/>";
|
|
3785
3909
|
strXml += ` <c:tickLblPos val="${opts.serAxisLabelPos || (opts.barDir === "col" ? "low" : "nextTo")}"/>`;
|
|
3786
|
-
strXml += "
|
|
3787
|
-
strXml += " <a:ln w=\"12700\" cap=\"flat\">";
|
|
3788
|
-
strXml += !opts.serAxisLineShow ? "<a:noFill/>" : genXmlColorSelection(opts.serAxisLineColor || DEF_GRIDLINE_COLOR);
|
|
3789
|
-
strXml += " <a:prstDash val=\"solid\"/>";
|
|
3790
|
-
strXml += " <a:round/>";
|
|
3791
|
-
strXml += " </a:ln>";
|
|
3792
|
-
strXml += " </c:spPr>";
|
|
3910
|
+
strXml += axisLineSpPr(2, EMU_PER_POINT, opts.serAxisLineShow, opts.serAxisLineColor, "solid");
|
|
3793
3911
|
strXml += " <c:txPr>";
|
|
3794
3912
|
strXml += " <a:bodyPr/>";
|
|
3795
3913
|
strXml += " <a:lstStyle/>";
|
|
@@ -5139,7 +5257,8 @@ function chartExLayoutId(type) {
|
|
|
5139
5257
|
/**
|
|
5140
5258
|
* A deterministic `uniqueId` GUID for a `<cx:series>`, derived from the chart's package-global id.
|
|
5141
5259
|
* PowerPoint stamps a random GUID here; deriving it keeps output byte-stable (the project pins
|
|
5142
|
-
* chart determinism —
|
|
5260
|
+
* chart determinism — the package-wide id this derives from is assigned at write time in
|
|
5261
|
+
* `package/assemble.ts`, STEP 2). `seriesIdx`
|
|
5143
5262
|
* distinguishes multiple series within one chart (pareto emits two), varying the 4th GUID group so
|
|
5144
5263
|
* every series still gets a distinct id.
|
|
5145
5264
|
*/
|
|
@@ -5383,9 +5502,15 @@ function makeXmlChartEx(rel) {
|
|
|
5383
5502
|
* template — analogous to the default theme/worksheet boilerplate the library already embeds. They
|
|
5384
5503
|
* reference theme scheme colors, so they adapt to the deck theme without per-chart customization.
|
|
5385
5504
|
*/
|
|
5386
|
-
/**
|
|
5505
|
+
/**
|
|
5506
|
+
* The `cs:colorStyle` payload for a chartEx chart's `colors{N}.xml` part (theme-accent cycle).
|
|
5507
|
+
* @raw-xml-asset Captured verbatim from PowerPoint; not built here, so not a migration target.
|
|
5508
|
+
*/
|
|
5387
5509
|
const CHARTEX_COLORS_BODY = "<cs:colorStyle xmlns:cs=\"http://schemas.microsoft.com/office/drawing/2012/chartStyle\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" meth=\"cycle\" id=\"10\"><a:schemeClr val=\"accent1\"/><a:schemeClr val=\"accent2\"/><a:schemeClr val=\"accent3\"/><a:schemeClr val=\"accent4\"/><a:schemeClr val=\"accent5\"/><a:schemeClr val=\"accent6\"/><cs:variation/><cs:variation><a:lumMod val=\"60000\"/></cs:variation><cs:variation><a:lumMod val=\"80000\"/><a:lumOff val=\"20000\"/></cs:variation><cs:variation><a:lumMod val=\"80000\"/></cs:variation><cs:variation><a:lumMod val=\"60000\"/><a:lumOff val=\"40000\"/></cs:variation><cs:variation><a:lumMod val=\"50000\"/></cs:variation><cs:variation><a:lumMod val=\"70000\"/><a:lumOff val=\"30000\"/></cs:variation><cs:variation><a:lumMod val=\"70000\"/></cs:variation><cs:variation><a:lumMod val=\"50000\"/><a:lumOff val=\"50000\"/></cs:variation></cs:colorStyle>";
|
|
5388
|
-
/**
|
|
5510
|
+
/**
|
|
5511
|
+
* The `cs:chartStyle` payload for a chartEx chart's `style{N}.xml` part (PowerPoint default).
|
|
5512
|
+
* @raw-xml-asset Captured verbatim from PowerPoint; not built here, so not a migration target.
|
|
5513
|
+
*/
|
|
5389
5514
|
const CHARTEX_STYLE_BODY = "<cs:chartStyle xmlns:cs=\"http://schemas.microsoft.com/office/drawing/2012/chartStyle\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" id=\"395\"><cs:axisTitle><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:defRPr sz=\"1197\"/></cs:axisTitle><cs:categoryAxis><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"15000\"/><a:lumOff val=\"85000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr><cs:defRPr sz=\"1197\"/></cs:categoryAxis><cs:chartArea mods=\"allowNoFillOverride allowNoLineOverride\"><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:solidFill><a:schemeClr val=\"bg1\"/></a:solidFill><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"15000\"/><a:lumOff val=\"85000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr><cs:defRPr sz=\"1330\"/></cs:chartArea><cs:dataLabel><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:defRPr sz=\"1197\"/></cs:dataLabel><cs:dataLabelCallout><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"dk1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:spPr><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill><a:ln><a:solidFill><a:schemeClr val=\"dk1\"><a:lumMod val=\"25000\"/><a:lumOff val=\"75000\"/></a:schemeClr></a:solidFill></a:ln></cs:spPr><cs:defRPr sz=\"1197\"/><cs:bodyPr rot=\"0\" spcFirstLastPara=\"1\" vertOverflow=\"clip\" horzOverflow=\"clip\" vert=\"horz\" wrap=\"square\" lIns=\"36576\" tIns=\"18288\" rIns=\"36576\" bIns=\"18288\" anchor=\"ctr\" anchorCtr=\"1\"><a:spAutoFit/></cs:bodyPr></cs:dataLabelCallout><cs:dataPoint><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"><cs:styleClr val=\"auto\"/></cs:fillRef><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill></cs:spPr></cs:dataPoint><cs:dataPoint3D><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"><cs:styleClr val=\"auto\"/></cs:fillRef><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill></cs:spPr></cs:dataPoint3D><cs:dataPointLine><cs:lnRef idx=\"0\"><cs:styleClr val=\"auto\"/></cs:lnRef><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"28575\" cap=\"rnd\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:round/></a:ln></cs:spPr></cs:dataPointLine><cs:dataPointMarker><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"><cs:styleClr val=\"auto\"/></cs:fillRef><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:ln w=\"9525\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></cs:spPr></cs:dataPointMarker><cs:dataPointMarkerLayout symbol=\"circle\" size=\"5\"/><cs:dataPointWireframe><cs:lnRef idx=\"0\"><cs:styleClr val=\"auto\"/></cs:lnRef><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"28575\" cap=\"rnd\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:round/></a:ln></cs:spPr></cs:dataPointWireframe><cs:dataTable><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:spPr><a:ln w=\"9525\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"15000\"/><a:lumOff val=\"85000\"/></a:schemeClr></a:solidFill></a:ln></cs:spPr><cs:defRPr sz=\"1197\"/></cs:dataTable><cs:downBar><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"dk1\"/></cs:fontRef><cs:spPr><a:solidFill><a:schemeClr val=\"dk1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></a:solidFill><a:ln w=\"9525\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></a:solidFill></a:ln></cs:spPr></cs:downBar><cs:dropLine><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"35000\"/><a:lumOff val=\"65000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr></cs:dropLine><cs:errorBar><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr></cs:errorBar><cs:floor><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef></cs:floor><cs:gridlineMajor><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"15000\"/><a:lumOff val=\"85000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr></cs:gridlineMajor><cs:gridlineMinor><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"15000\"/><a:lumOff val=\"85000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr></cs:gridlineMinor><cs:hiLoLine><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"75000\"/><a:lumOff val=\"25000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr></cs:hiLoLine><cs:leaderLine><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"35000\"/><a:lumOff val=\"65000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr></cs:leaderLine><cs:legend><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:defRPr sz=\"1197\"/></cs:legend><cs:plotArea mods=\"allowNoFillOverride allowNoLineOverride\"><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef></cs:plotArea><cs:plotArea3D mods=\"allowNoFillOverride allowNoLineOverride\"><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef></cs:plotArea3D><cs:seriesAxis><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"15000\"/><a:lumOff val=\"85000\"/></a:schemeClr></a:solidFill><a:round/></a:ln></cs:spPr><cs:defRPr sz=\"1197\"/></cs:seriesAxis><cs:seriesLine><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"9525\" cap=\"flat\"><a:solidFill><a:srgbClr val=\"D9D9D9\"/></a:solidFill><a:round/></a:ln></cs:spPr></cs:seriesLine><cs:title><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:defRPr sz=\"1862\"/></cs:title><cs:trendline><cs:lnRef idx=\"0\"><cs:styleClr val=\"auto\"/></cs:lnRef><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef><cs:spPr><a:ln w=\"19050\" cap=\"rnd\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:prstDash val=\"sysDash\"/></a:ln></cs:spPr></cs:trendline><cs:trendlineLabel><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:defRPr sz=\"1197\"/></cs:trendlineLabel><cs:upBar><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"dk1\"/></cs:fontRef><cs:spPr><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill><a:ln w=\"9525\"><a:solidFill><a:schemeClr val=\"tx1\"><a:lumMod val=\"15000\"/><a:lumOff val=\"85000\"/></a:schemeClr></a:solidFill></a:ln></cs:spPr></cs:upBar><cs:valueAxis><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"><a:lumMod val=\"65000\"/><a:lumOff val=\"35000\"/></a:schemeClr></cs:fontRef><cs:defRPr sz=\"1197\"/></cs:valueAxis><cs:wall><cs:lnRef idx=\"0\"/><cs:fillRef idx=\"0\"/><cs:effectRef idx=\"0\"/><cs:fontRef idx=\"minor\"><a:schemeClr val=\"tx1\"/></cs:fontRef></cs:wall></cs:chartStyle>";
|
|
5390
5515
|
/** Build the `ppt/charts/colors{N}.xml` part body. */
|
|
5391
5516
|
function makeChartExColorsXml() {
|
|
@@ -5397,7 +5522,6 @@ function makeChartExStyleXml() {
|
|
|
5397
5522
|
}
|
|
5398
5523
|
//#endregion
|
|
5399
5524
|
//#region src/gen/chart/embed-xlsx.ts
|
|
5400
|
-
const PACKAGE_REL_NS$2 = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
5401
5525
|
function relationship$2(id, type, target) {
|
|
5402
5526
|
return voidEl("Relationship", {
|
|
5403
5527
|
Id: id,
|
|
@@ -5407,7 +5531,7 @@ function relationship$2(id, type, target) {
|
|
|
5407
5531
|
}
|
|
5408
5532
|
/** `<Relationships>` wrapper shared by the workbook's `.rels` parts (all flat, no indent). */
|
|
5409
5533
|
function relationships(rels) {
|
|
5410
|
-
return el("Relationships", { xmlns: PACKAGE_REL_NS
|
|
5534
|
+
return el("Relationships", { xmlns: PACKAGE_REL_NS }, rels.map(raw));
|
|
5411
5535
|
}
|
|
5412
5536
|
/**
|
|
5413
5537
|
* Build the chart's embedded Excel workbook as a standalone OPC package and
|
|
@@ -5426,22 +5550,22 @@ function buildEmbeddedWorksheet(chartObject) {
|
|
|
5426
5550
|
const IS_MULTI_CAT_AXES = (data[0]?.labels?.length ?? 0) > 1;
|
|
5427
5551
|
zipExcel.add("[Content_Types].xml", XML_DECL + "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"> <Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/> <Default Extension=\"xml\" ContentType=\"application/xml\"/> <Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/> <Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/> <Override PartName=\"/xl/theme/theme1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.theme+xml\"/> <Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/> <Override PartName=\"/xl/sharedStrings.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml\"/> <Override PartName=\"/xl/tables/table1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml\"/> <Override PartName=\"/docProps/core.xml\" ContentType=\"application/vnd.openxmlformats-package.core-properties+xml\"/> <Override PartName=\"/docProps/app.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.extended-properties+xml\"/></Types>\n");
|
|
5428
5552
|
zipExcel.add("_rels/.rels", XML_DECL + relationships([
|
|
5429
|
-
relationship$2("rId1", "
|
|
5430
|
-
relationship$2("rId2", "
|
|
5431
|
-
relationship$2("rId3", "
|
|
5553
|
+
relationship$2("rId1", PACKAGE_REL_NS + "/metadata/core-properties", "docProps/core.xml"),
|
|
5554
|
+
relationship$2("rId2", OFFICE_REL + "extended-properties", "docProps/app.xml"),
|
|
5555
|
+
relationship$2("rId3", OFFICE_REL + "officeDocument", "xl/workbook.xml")
|
|
5432
5556
|
]) + "\n");
|
|
5433
5557
|
zipExcel.add("docProps/app.xml", XML_DECL + "<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\"><Application>Microsoft Macintosh Excel</Application><DocSecurity>0</DocSecurity><ScaleCrop>false</ScaleCrop><HeadingPairs><vt:vector size=\"2\" baseType=\"variant\"><vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant><vt:variant><vt:i4>1</vt:i4></vt:variant></vt:vector></HeadingPairs><TitlesOfParts><vt:vector size=\"1\" baseType=\"lpstr\"><vt:lpstr>Sheet1</vt:lpstr></vt:vector></TitlesOfParts><Company></Company><LinksUpToDate>false</LinksUpToDate><SharedDoc>false</SharedDoc><HyperlinksChanged>false</HyperlinksChanged><AppVersion>16.0300</AppVersion></Properties>\n");
|
|
5434
5558
|
zipExcel.add("docProps/core.xml", XML_DECL + "<cp:coreProperties xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/core-properties\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><dc:creator>TsPptx</dc:creator><cp:lastModifiedBy>TsPptx</cp:lastModifiedBy><dcterms:created xsi:type=\"dcterms:W3CDTF\">" + (/* @__PURE__ */ new Date()).toISOString() + "</dcterms:created><dcterms:modified xsi:type=\"dcterms:W3CDTF\">" + (/* @__PURE__ */ new Date()).toISOString() + "</dcterms:modified></cp:coreProperties>");
|
|
5435
5559
|
zipExcel.add("xl/_rels/workbook.xml.rels", XML_DECL + relationships([
|
|
5436
|
-
relationship$2("rId3", "
|
|
5437
|
-
relationship$2("rId2", "
|
|
5438
|
-
relationship$2("rId1", "
|
|
5439
|
-
relationship$2("rId4", "
|
|
5560
|
+
relationship$2("rId3", OFFICE_REL + "styles", "styles.xml"),
|
|
5561
|
+
relationship$2("rId2", OFFICE_REL + "theme", "theme/theme1.xml"),
|
|
5562
|
+
relationship$2("rId1", OFFICE_REL + "worksheet", "worksheets/sheet1.xml"),
|
|
5563
|
+
relationship$2("rId4", OFFICE_REL + "sharedStrings", "sharedStrings.xml")
|
|
5440
5564
|
]));
|
|
5441
5565
|
zipExcel.add("xl/styles.xml", XML_DECL + "<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><numFmts count=\"1\"><numFmt numFmtId=\"0\" formatCode=\"General\"/></numFmts><fonts count=\"4\"><font><sz val=\"9\"/><color indexed=\"8\"/><name val=\"Geneva\"/></font><font><sz val=\"9\"/><color indexed=\"8\"/><name val=\"Geneva\"/></font><font><sz val=\"10\"/><color indexed=\"8\"/><name val=\"Geneva\"/></font><font><sz val=\"18\"/><color indexed=\"8\"/><name val=\"Arial\"/></font></fonts><fills count=\"2\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"gray125\"/></fill></fills><borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders><dxfs count=\"0\"/><tableStyles count=\"0\"/><colors><indexedColors><rgbColor rgb=\"ff000000\"/><rgbColor rgb=\"ffffffff\"/><rgbColor rgb=\"ffff0000\"/><rgbColor rgb=\"ff00ff00\"/><rgbColor rgb=\"ff0000ff\"/><rgbColor rgb=\"ffffff00\"/><rgbColor rgb=\"ffff00ff\"/><rgbColor rgb=\"ff00ffff\"/><rgbColor rgb=\"ff000000\"/><rgbColor rgb=\"ffffffff\"/><rgbColor rgb=\"ff878787\"/><rgbColor rgb=\"fff9f9f9\"/></indexedColors></colors></styleSheet>\n");
|
|
5442
5566
|
zipExcel.add("xl/theme/theme1.xml", XML_DECL + "<a:theme xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" name=\"Office Theme\"><a:themeElements><a:clrScheme name=\"Office\"><a:dk1><a:sysClr val=\"windowText\" lastClr=\"000000\"/></a:dk1><a:lt1><a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1><a:dk2><a:srgbClr val=\"44546A\"/></a:dk2><a:lt2><a:srgbClr val=\"E7E6E6\"/></a:lt2><a:accent1><a:srgbClr val=\"4472C4\"/></a:accent1><a:accent2><a:srgbClr val=\"ED7D31\"/></a:accent2><a:accent3><a:srgbClr val=\"A5A5A5\"/></a:accent3><a:accent4><a:srgbClr val=\"FFC000\"/></a:accent4><a:accent5><a:srgbClr val=\"5B9BD5\"/></a:accent5><a:accent6><a:srgbClr val=\"70AD47\"/></a:accent6><a:hlink><a:srgbClr val=\"0563C1\"/></a:hlink><a:folHlink><a:srgbClr val=\"954F72\"/></a:folHlink></a:clrScheme><a:fontScheme name=\"Office\"><a:majorFont><a:latin typeface=\"Calibri Light\" panose=\"020F0302020204030204\"/><a:ea typeface=\"\"/><a:cs typeface=\"\"/><a:font script=\"Jpan\" typeface=\"Yu Gothic Light\"/><a:font script=\"Hang\" typeface=\"맑은 고딕\"/><a:font script=\"Hans\" typeface=\"DengXian Light\"/><a:font script=\"Hant\" typeface=\"新細明體\"/><a:font script=\"Arab\" typeface=\"Times New Roman\"/><a:font script=\"Hebr\" typeface=\"Times New Roman\"/><a:font script=\"Thai\" typeface=\"Tahoma\"/><a:font script=\"Ethi\" typeface=\"Nyala\"/><a:font script=\"Beng\" typeface=\"Vrinda\"/><a:font script=\"Gujr\" typeface=\"Shruti\"/><a:font script=\"Khmr\" typeface=\"MoolBoran\"/><a:font script=\"Knda\" typeface=\"Tunga\"/><a:font script=\"Guru\" typeface=\"Raavi\"/><a:font script=\"Cans\" typeface=\"Euphemia\"/><a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/><a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/><a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/><a:font script=\"Thaa\" typeface=\"MV Boli\"/><a:font script=\"Deva\" typeface=\"Mangal\"/><a:font script=\"Telu\" typeface=\"Gautami\"/><a:font script=\"Taml\" typeface=\"Latha\"/><a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/><a:font script=\"Orya\" typeface=\"Kalinga\"/><a:font script=\"Mlym\" typeface=\"Kartika\"/><a:font script=\"Laoo\" typeface=\"DokChampa\"/><a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/><a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/><a:font script=\"Viet\" typeface=\"Times New Roman\"/><a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/><a:font script=\"Geor\" typeface=\"Sylfaen\"/></a:majorFont><a:minorFont><a:latin typeface=\"Calibri\" panose=\"020F0502020204030204\"/><a:ea typeface=\"\"/><a:cs typeface=\"\"/><a:font script=\"Jpan\" typeface=\"Yu Gothic\"/><a:font script=\"Hang\" typeface=\"맑은 고딕\"/><a:font script=\"Hans\" typeface=\"DengXian\"/><a:font script=\"Hant\" typeface=\"新細明體\"/><a:font script=\"Arab\" typeface=\"Arial\"/><a:font script=\"Hebr\" typeface=\"Arial\"/><a:font script=\"Thai\" typeface=\"Tahoma\"/><a:font script=\"Ethi\" typeface=\"Nyala\"/><a:font script=\"Beng\" typeface=\"Vrinda\"/><a:font script=\"Gujr\" typeface=\"Shruti\"/><a:font script=\"Khmr\" typeface=\"DaunPenh\"/><a:font script=\"Knda\" typeface=\"Tunga\"/><a:font script=\"Guru\" typeface=\"Raavi\"/><a:font script=\"Cans\" typeface=\"Euphemia\"/><a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/><a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/><a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/><a:font script=\"Thaa\" typeface=\"MV Boli\"/><a:font script=\"Deva\" typeface=\"Mangal\"/><a:font script=\"Telu\" typeface=\"Gautami\"/><a:font script=\"Taml\" typeface=\"Latha\"/><a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/><a:font script=\"Orya\" typeface=\"Kalinga\"/><a:font script=\"Mlym\" typeface=\"Kartika\"/><a:font script=\"Laoo\" typeface=\"DokChampa\"/><a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/><a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/><a:font script=\"Viet\" typeface=\"Arial\"/><a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/><a:font script=\"Geor\" typeface=\"Sylfaen\"/></a:minorFont></a:fontScheme><a:fmtScheme name=\"Office\"><a:fillStyleLst><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:gradFill rotWithShape=\"1\"><a:gsLst><a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:lumMod val=\"110000\"/><a:satMod val=\"105000\"/><a:tint val=\"67000\"/></a:schemeClr></a:gs><a:gs pos=\"50000\"><a:schemeClr val=\"phClr\"><a:lumMod val=\"105000\"/><a:satMod val=\"103000\"/><a:tint val=\"73000\"/></a:schemeClr></a:gs><a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:lumMod val=\"105000\"/><a:satMod val=\"109000\"/><a:tint val=\"81000\"/></a:schemeClr></a:gs></a:gsLst><a:lin ang=\"5400000\" scaled=\"0\"/></a:gradFill><a:gradFill rotWithShape=\"1\"><a:gsLst><a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:satMod val=\"103000\"/><a:lumMod val=\"102000\"/><a:tint val=\"94000\"/></a:schemeClr></a:gs><a:gs pos=\"50000\"><a:schemeClr val=\"phClr\"><a:satMod val=\"110000\"/><a:lumMod val=\"100000\"/><a:shade val=\"100000\"/></a:schemeClr></a:gs><a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:lumMod val=\"99000\"/><a:satMod val=\"120000\"/><a:shade val=\"78000\"/></a:schemeClr></a:gs></a:gsLst><a:lin ang=\"5400000\" scaled=\"0\"/></a:gradFill></a:fillStyleLst><a:lnStyleLst><a:ln w=\"6350\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:prstDash val=\"solid\"/><a:miter lim=\"800000\"/></a:ln><a:ln w=\"12700\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:prstDash val=\"solid\"/><a:miter lim=\"800000\"/></a:ln><a:ln w=\"19050\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:prstDash val=\"solid\"/><a:miter lim=\"800000\"/></a:ln></a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst><a:outerShdw blurRad=\"57150\" dist=\"19050\" dir=\"5400000\" algn=\"ctr\" rotWithShape=\"0\"><a:srgbClr val=\"000000\"><a:alpha val=\"63000\"/></a:srgbClr></a:outerShdw></a:effectLst></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill><a:solidFill><a:schemeClr val=\"phClr\"><a:tint val=\"95000\"/><a:satMod val=\"170000\"/></a:schemeClr></a:solidFill><a:gradFill rotWithShape=\"1\"><a:gsLst><a:gs pos=\"0\"><a:schemeClr val=\"phClr\"><a:tint val=\"93000\"/><a:satMod val=\"150000\"/><a:shade val=\"98000\"/><a:lumMod val=\"102000\"/></a:schemeClr></a:gs><a:gs pos=\"50000\"><a:schemeClr val=\"phClr\"><a:tint val=\"98000\"/><a:satMod val=\"130000\"/><a:shade val=\"90000\"/><a:lumMod val=\"103000\"/></a:schemeClr></a:gs><a:gs pos=\"100000\"><a:schemeClr val=\"phClr\"><a:shade val=\"63000\"/><a:satMod val=\"120000\"/></a:schemeClr></a:gs></a:gsLst><a:lin ang=\"5400000\" scaled=\"0\"/></a:gradFill></a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults/><a:extraClrSchemeLst/><a:extLst><a:ext uri=\"{05A4C25C-085E-4340-85A3-A5531E510DB2}\"><thm15:themeFamily xmlns:thm15=\"http://schemas.microsoft.com/office/thememl/2012/main\" name=\"Office Theme\" id=\"{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}\" vid=\"{4A3C46E8-61CC-4603-A589-7422A47A8E4A}\"/></a:ext></a:extLst></a:theme>");
|
|
5443
5567
|
zipExcel.add("xl/workbook.xml", XML_DECL + "<workbook 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=\"x15\" xmlns:x15=\"http://schemas.microsoft.com/office/spreadsheetml/2010/11/main\"><fileVersion appName=\"xl\" lastEdited=\"7\" lowestEdited=\"6\" rupBuild=\"10507\"/><workbookPr/><bookViews><workbookView xWindow=\"0\" yWindow=\"500\" windowWidth=\"20960\" windowHeight=\"15960\"/></bookViews><sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets><calcPr calcId=\"0\" concurrentCalc=\"0\"/></workbook>\n");
|
|
5444
|
-
zipExcel.add("xl/worksheets/_rels/sheet1.xml.rels", XML_DECL + relationships([relationship$2("rId1", "
|
|
5568
|
+
zipExcel.add("xl/worksheets/_rels/sheet1.xml.rels", XML_DECL + relationships([relationship$2("rId1", OFFICE_REL + "table", "../tables/table1.xml")]) + "\n");
|
|
5445
5569
|
zipExcel.add("xl/sharedStrings.xml", buildXlsxSharedStrings(chartObject, data, intBubbleCols, IS_MULTI_CAT_AXES));
|
|
5446
5570
|
zipExcel.add("xl/tables/table1.xml", buildXlsxTable(chartObject, data, intBubbleCols));
|
|
5447
5571
|
zipExcel.add("xl/worksheets/sheet1.xml", buildXlsxSheet(chartObject, data, intBubbleCols, IS_MULTI_CAT_AXES));
|
|
@@ -5622,7 +5746,7 @@ function buildXlsxSheet(chartObject, data, intBubbleCols, IS_MULTI_CAT_AXES) {
|
|
|
5622
5746
|
* @return {string} the chart part's `.rels` XML
|
|
5623
5747
|
*/
|
|
5624
5748
|
function buildChartRelsXml(embeddingTarget) {
|
|
5625
|
-
return XML_DECL + relationships([relationship$2("rId1", "
|
|
5749
|
+
return XML_DECL + relationships([relationship$2("rId1", OFFICE_REL + "package", embeddingTarget)]);
|
|
5626
5750
|
}
|
|
5627
5751
|
/**
|
|
5628
5752
|
* Build the `.rels` for a chartEx chart part: the embedded workbook (rId1, via `<cx:externalData>`)
|
|
@@ -5634,7 +5758,7 @@ function buildChartRelsXml(embeddingTarget) {
|
|
|
5634
5758
|
*/
|
|
5635
5759
|
function buildChartExRelsXml(embeddingTarget, colorsTarget, styleTarget) {
|
|
5636
5760
|
return XML_DECL + relationships([
|
|
5637
|
-
relationship$2("rId1", "
|
|
5761
|
+
relationship$2("rId1", OFFICE_REL + "package", embeddingTarget),
|
|
5638
5762
|
relationship$2("rId2", "http://schemas.microsoft.com/office/2011/relationships/chartColorStyle", colorsTarget),
|
|
5639
5763
|
relationship$2("rId3", "http://schemas.microsoft.com/office/2011/relationships/chartStyle", styleTarget)
|
|
5640
5764
|
]);
|
|
@@ -5752,6 +5876,63 @@ function encodeSlideMediaRels(layout, runtime, onMediaError = "throw") {
|
|
|
5752
5876
|
return imageProms;
|
|
5753
5877
|
}
|
|
5754
5878
|
//#endregion
|
|
5879
|
+
//#region src/gen/prepare.ts
|
|
5880
|
+
/**
|
|
5881
|
+
* ts-pptx: the pre-serialization pass
|
|
5882
|
+
*
|
|
5883
|
+
* Everything that must happen to authored slide state *before* any XML is built. Two callers
|
|
5884
|
+
* reach serialization and both need it:
|
|
5885
|
+
*
|
|
5886
|
+
* - `package/assemble.ts` — the normal `write`/`stream`/`writeFile` path, building a
|
|
5887
|
+
* complete `.pptx`.
|
|
5888
|
+
* - `PresentationCore.extractSlides()` — serializes slide bodies only, for splicing into
|
|
5889
|
+
* an already-loaded deck via `Presentation.appendSlides()` (`ts-pptx/read`).
|
|
5890
|
+
*
|
|
5891
|
+
* The second used to reimplement the first inline, kept in step by a comment that said
|
|
5892
|
+
* "exactly as ... does". Nothing failed when they drifted: `extractSlides` would simply emit
|
|
5893
|
+
* slides that did not match what a normal write produces, and no test compares the two.
|
|
5894
|
+
*
|
|
5895
|
+
* Two primitives rather than one combined pass, because the package path has work of its own
|
|
5896
|
+
* that must land *between* them: it de-duplicates identical media across the deck (which
|
|
5897
|
+
* needs the encoded bytes {@link encodeMediaForTargets} produces) and assigns package-unique
|
|
5898
|
+
* chart part filenames, both before any slide content is baked. Exposing the halves lets
|
|
5899
|
+
* `assemble` keep its established order exactly while still sharing the code.
|
|
5900
|
+
*
|
|
5901
|
+
* The order across the two is load-bearing:
|
|
5902
|
+
*
|
|
5903
|
+
* 1. **Media first.** It is the only asynchronous step, and the sync XML pass reads the
|
|
5904
|
+
* `rel.data` it populates.
|
|
5905
|
+
* 2. **Backfill placeholders**, so a slide inherits its layout's placeholder objects before
|
|
5906
|
+
* anything measures or serializes them.
|
|
5907
|
+
* 3. **Bake measured fit last**, because it measures the text step 2 may have just added and
|
|
5908
|
+
* writes the `fontScale` the sync XML pass then reads.
|
|
5909
|
+
*
|
|
5910
|
+
* The two functions take different target sets on purpose: media lives on layouts and the
|
|
5911
|
+
* master as well as on slides, while placeholder backfill and measured fit apply only to
|
|
5912
|
+
* slides. `extractSlides` passes only its slides to both, because it emits no layout or
|
|
5913
|
+
* master parts.
|
|
5914
|
+
*/
|
|
5915
|
+
/**
|
|
5916
|
+
* Step 1: load and base64-encode every media rel on the given targets, populating `rel.data`.
|
|
5917
|
+
* @param {ReadonlyArray<PresSlideInternal | SlideLayoutInternal>} targets - media-bearing targets (slides, layouts, master)
|
|
5918
|
+
* @param {RuntimeAdapter} runtime - runtime adapter used to load media
|
|
5919
|
+
* @param {'throw' | 'placeholder'} onMediaError - failure policy for unloadable media
|
|
5920
|
+
*/
|
|
5921
|
+
async function encodeMediaForTargets(targets, runtime, onMediaError) {
|
|
5922
|
+
const promises = [];
|
|
5923
|
+
for (const target of targets) promises.push(...encodeSlideMediaRels(target, runtime, onMediaError));
|
|
5924
|
+
await Promise.all(promises);
|
|
5925
|
+
}
|
|
5926
|
+
/**
|
|
5927
|
+
* Steps 2 and 3: backfill inherited layout placeholders, then bake measured text fit.
|
|
5928
|
+
* @param {PresSlideInternal[]} slides - the slides to prepare
|
|
5929
|
+
* @param {FontMetricsRegistry} fontMetrics - registered font metrics; an empty registry skips the fit bake
|
|
5930
|
+
*/
|
|
5931
|
+
function bakeSlideContent(slides, fontMetrics) {
|
|
5932
|
+
for (const slide of slides) if (slide._slideLayout) addPlaceholdersToSlideLayouts(slide);
|
|
5933
|
+
applyMeasuredFit(slides, fontMetrics);
|
|
5934
|
+
}
|
|
5935
|
+
//#endregion
|
|
5755
5936
|
//#region src/gen/slide/shape-ids.ts
|
|
5756
5937
|
/**
|
|
5757
5938
|
* Every object a slide renders, paired with the `<p:cNvPr>` id it is rendered with: top-level
|
|
@@ -5761,7 +5942,7 @@ function encodeSlideMediaRels(layout, runtime, onMediaError = "throw") {
|
|
|
5761
5942
|
* This **mirrors** the allocation in `slideObjectToXml`, which hands out ids as it walks the tree.
|
|
5762
5943
|
* A reference that must name an id *before* the walk reaches it — a connector's `<a:stCxn>`, an
|
|
5763
5944
|
* animation's `<p:spTgt spid>` — cannot wait for that, so it resolves through this map instead.
|
|
5764
|
-
* The two must stay in step: `test/regression/group-shapes.test.js` parses the emitted `cNvPr` ids
|
|
5945
|
+
* The two must stay in step: `test/regression/shape/group-shapes.test.js` parses the emitted `cNvPr` ids
|
|
5765
5946
|
* back out and asserts each reference points at the shape it names, so drift fails there.
|
|
5766
5947
|
* @param slideObjects - the slide's top-level objects
|
|
5767
5948
|
* @returns each object's `<p:cNvPr>` id, keyed by object identity, in id order
|
|
@@ -6482,13 +6663,13 @@ function genXmlParagraphProperties(textObj, isDefault) {
|
|
|
6482
6663
|
const isPictureBullet = !!(bulletImage && (bulletImage.path || bulletImage.data));
|
|
6483
6664
|
if (opts.bullet?.indent) bulletMarL = valToPts(opts.bullet.indent);
|
|
6484
6665
|
if (opts.bullet.color && !isPictureBullet) strXmlBulletColor = el("a:buClr", null, raw(createColorElement(opts.bullet.color)));
|
|
6485
|
-
let bulletSizePct
|
|
6666
|
+
let bulletSizePct;
|
|
6486
6667
|
if (opts.bullet.size !== void 0) {
|
|
6487
6668
|
const bulletSize = Number(opts.bullet.size);
|
|
6488
6669
|
if (isNaN(bulletSize) || bulletSize < 25 || bulletSize > 400) warn("bullet/size-out-of-range", "`bullet.size` must be a percentage between 25 and 400!");
|
|
6489
6670
|
else bulletSizePct = Math.round(bulletSize * FIXED_PCT_PER_PERCENT);
|
|
6490
6671
|
}
|
|
6491
|
-
const strXmlBulletSize = voidEl("a:buSzPct", { val: bulletSizePct });
|
|
6672
|
+
const strXmlBulletSize = bulletSizePct === void 0 ? "" : voidEl("a:buSzPct", { val: bulletSizePct });
|
|
6492
6673
|
const strXmlBulletFont = opts.bullet.fontFace ? voidEl("a:buFont", { typeface: opts.bullet.fontFace }) : "";
|
|
6493
6674
|
const bulletIndentAttrs = () => ` marL="${opts.indentLevel && opts.indentLevel > 0 ? bulletMarL + bulletMarL * opts.indentLevel : bulletMarL}" indent="-${bulletMarL}"`;
|
|
6494
6675
|
if (isPictureBullet) {
|
|
@@ -6523,7 +6704,7 @@ function genXmlParagraphProperties(textObj, isDefault) {
|
|
|
6523
6704
|
}
|
|
6524
6705
|
} else if (opts.bullet) {
|
|
6525
6706
|
paragraphPropXml += ` marL="${opts.indentLevel && opts.indentLevel > 0 ? bulletMarL + bulletMarL * opts.indentLevel : bulletMarL}" indent="-${bulletMarL}"`;
|
|
6526
|
-
strXmlBullet =
|
|
6707
|
+
strXmlBullet = buChar("•");
|
|
6527
6708
|
} else if (!opts.bullet) {
|
|
6528
6709
|
paragraphPropXml += " indent=\"0\" marL=\"0\"";
|
|
6529
6710
|
strXmlBullet = voidEl("a:buNone");
|
|
@@ -6655,7 +6836,7 @@ function groupRunsIntoLines(arrTextObjects, opts) {
|
|
|
6655
6836
|
arrLines.push(arrTexts);
|
|
6656
6837
|
arrTexts = [];
|
|
6657
6838
|
}
|
|
6658
|
-
} else if (arrTexts.length > 0 && textObj.options.bullet
|
|
6839
|
+
} else if (arrTexts.length > 0 && textObj.options.bullet) {
|
|
6659
6840
|
arrLines.push(arrTexts);
|
|
6660
6841
|
arrTexts = [];
|
|
6661
6842
|
textObj.options.breakLine = false;
|
|
@@ -7299,28 +7480,31 @@ function genXmlCustGeom(options, cx, cy, layout) {
|
|
|
7299
7480
|
* ts-pptx: DrawingML image sizing & cropping
|
|
7300
7481
|
*
|
|
7301
7482
|
* Build the `<a:srcRect>` (+ `<a:stretch>`) blipFill children for the image
|
|
7302
|
-
* sizing modes (`cover` / `contain` / `crop`)
|
|
7483
|
+
* sizing modes (`cover` / `contain` / `crop` / `stretch`), for the implicit
|
|
7484
|
+
* aspect-correct placement a vector source gets, and for explicit percentage crops.
|
|
7303
7485
|
*/
|
|
7304
7486
|
/** Every `<a:srcRect>` below is followed by this same fill directive. */
|
|
7305
7487
|
const STRETCH = el("a:stretch", null, raw(voidEl("a:fillRect")));
|
|
7488
|
+
/** The `<a:srcRect>` fitting `imgSize` into `boxDim`, followed by the fill directive. */
|
|
7489
|
+
function fitSrcRect(type, imgSize, boxDim) {
|
|
7490
|
+
const { l, r, t, b } = fitSrcRectPercents(type, imgSize, boxDim);
|
|
7491
|
+
return voidEl("a:srcRect", {
|
|
7492
|
+
l,
|
|
7493
|
+
r,
|
|
7494
|
+
t,
|
|
7495
|
+
b
|
|
7496
|
+
}) + STRETCH;
|
|
7497
|
+
}
|
|
7306
7498
|
const ImageSizingXml = {
|
|
7307
7499
|
cover: function(imgSize, boxDim) {
|
|
7308
|
-
|
|
7309
|
-
return voidEl("a:srcRect", {
|
|
7310
|
-
l,
|
|
7311
|
-
r,
|
|
7312
|
-
t,
|
|
7313
|
-
b
|
|
7314
|
-
}) + STRETCH;
|
|
7500
|
+
return fitSrcRect("cover", imgSize, boxDim);
|
|
7315
7501
|
},
|
|
7316
7502
|
contain: function(imgSize, boxDim) {
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
b
|
|
7323
|
-
}) + STRETCH;
|
|
7503
|
+
return fitSrcRect("contain", imgSize, boxDim);
|
|
7504
|
+
},
|
|
7505
|
+
/** No source rectangle at all: the image fills the box, aspect ratio be damned. */
|
|
7506
|
+
stretch: function() {
|
|
7507
|
+
return STRETCH;
|
|
7324
7508
|
},
|
|
7325
7509
|
crop: function(imgSize, boxDim) {
|
|
7326
7510
|
const l = boxDim.x;
|
|
@@ -7345,6 +7529,23 @@ const ImageSizingXml = {
|
|
|
7345
7529
|
}
|
|
7346
7530
|
};
|
|
7347
7531
|
/**
|
|
7532
|
+
* The blipFill children for a vector source the caller gave no `sizing` for: letterbox it to its
|
|
7533
|
+
* own aspect ratio inside its frame, the way `sizing: 'contain'` would — an SVG carries an
|
|
7534
|
+
* intrinsic ratio, and stretching a glyph into a box that disagrees with it is never the intent.
|
|
7535
|
+
*
|
|
7536
|
+
* Returns `null` when the two ratios already agree, which is the overwhelmingly common case (a
|
|
7537
|
+
* square icon in a square box). The caller then emits the plain `<a:stretch>` it always did, so
|
|
7538
|
+
* this default costs nothing — neither bytes nor a behaviour change — until it actually differs.
|
|
7539
|
+
* @param imgSize - the vector's intrinsic size (viewBox or width/height)
|
|
7540
|
+
* @param boxDim - the picture's displayed frame
|
|
7541
|
+
* @returns the `<a:srcRect>` + `<a:stretch>` children, or `null` if no letterboxing is needed
|
|
7542
|
+
*/
|
|
7543
|
+
function genXmlVectorAspectFit(imgSize, boxDim) {
|
|
7544
|
+
const { l, r, t, b } = fitSrcRectPercents("contain", imgSize, boxDim);
|
|
7545
|
+
if (l === 0 && r === 0 && t === 0 && b === 0) return null;
|
|
7546
|
+
return fitSrcRect("contain", imgSize, boxDim);
|
|
7547
|
+
}
|
|
7548
|
+
/**
|
|
7348
7549
|
* Build an explicit `<a:srcRect>` crop from percentage edge insets (0–100), emitted verbatim.
|
|
7349
7550
|
* Each inset is the percent of the *source* image trimmed from that edge; values serialize in
|
|
7350
7551
|
* 1000ths of a percent (DrawingML `ST_Percentage`, where 100% = 100000). Unlike `sizing: 'crop'`
|
|
@@ -7381,10 +7582,12 @@ function genXmlImageCrop(crop, objectName) {
|
|
|
7381
7582
|
function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, imgHeight, placeholderObj, locationAttrs, sizing, rounding) {
|
|
7382
7583
|
let strSlideXml = "";
|
|
7383
7584
|
slideItemObj.options = slideItemObj.options || {};
|
|
7585
|
+
const mediaRel = (slide._relsMedia || []).find((rel) => rel.rId === slideItemObj.imageRid);
|
|
7586
|
+
const relData = mediaRel?.data;
|
|
7587
|
+
const naturalSize = () => typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
7384
7588
|
if (slideItemObj.options._szAuto) {
|
|
7385
7589
|
const szAuto = slideItemObj.options._szAuto;
|
|
7386
|
-
const
|
|
7387
|
-
const natural = typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
7590
|
+
const natural = naturalSize();
|
|
7388
7591
|
if (natural) {
|
|
7389
7592
|
if (szAuto.w && szAuto.h) {
|
|
7390
7593
|
cx = pixelsToEmu(natural.w, 96);
|
|
@@ -7415,7 +7618,8 @@ function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, img
|
|
|
7415
7618
|
imgOpts.biLevel ? raw(voidEl("a:biLevel", { thresh: Math.round(imgOpts.biLevel.threshold * PERCENT_SCALE) })) : null
|
|
7416
7619
|
];
|
|
7417
7620
|
strSlideXml += "<p:blipFill>";
|
|
7418
|
-
|
|
7621
|
+
const isVector = mediaRel?.extn === "svg";
|
|
7622
|
+
if (isVector) strSlideXml += el("a:blip", { "r:embed": `rId${(slideItemObj.imageRid ?? 0) - 1}` }, [...blipEffects(" "), raw(el("a:extLst", null, raw(el("a:ext", { uri: "{96DAC541-7B7A-43D3-8B79-37D633B846F1}" }, raw(voidEl("asvg:svgBlip", {
|
|
7419
7623
|
"xmlns:asvg": "http://schemas.microsoft.com/office/drawing/2016/SVG/main",
|
|
7420
7624
|
"r:embed": `rId${slideItemObj.imageRid}`
|
|
7421
7625
|
}, { openPrefix: " " })), {
|
|
@@ -7439,8 +7643,7 @@ function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, img
|
|
|
7439
7643
|
h: imgHeight
|
|
7440
7644
|
};
|
|
7441
7645
|
if (sizing.type === "cover" || sizing.type === "contain") {
|
|
7442
|
-
const
|
|
7443
|
-
const natural = typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
7646
|
+
const natural = naturalSize();
|
|
7444
7647
|
if (natural) cropSize = natural;
|
|
7445
7648
|
else warn("image/unmeasurable-natural-size", `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) or an SVG with width/height or a viewBox to enable an aspect-correct crop.`);
|
|
7446
7649
|
}
|
|
@@ -7452,7 +7655,14 @@ function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, img
|
|
|
7452
7655
|
});
|
|
7453
7656
|
imgWidth = boxW;
|
|
7454
7657
|
imgHeight = boxH;
|
|
7455
|
-
} else
|
|
7658
|
+
} else {
|
|
7659
|
+
const natural = isVector ? naturalSize() : null;
|
|
7660
|
+
const aspectFit = natural ? genXmlVectorAspectFit(natural, {
|
|
7661
|
+
w: imgWidth,
|
|
7662
|
+
h: imgHeight
|
|
7663
|
+
}) : null;
|
|
7664
|
+
strSlideXml += aspectFit ?? el("a:stretch", null, raw(voidEl("a:fillRect")), { openPrefix: " " });
|
|
7665
|
+
}
|
|
7456
7666
|
strSlideXml += "</p:blipFill>";
|
|
7457
7667
|
strSlideXml += "<p:spPr>";
|
|
7458
7668
|
strSlideXml += el("a:xfrm", locationAttrs, [raw(voidEl("a:off", {
|
|
@@ -7526,6 +7736,216 @@ function renderMediaObject(slideItemObj, idx, x, y, cx, cy, locationAttrs) {
|
|
|
7526
7736
|
]);
|
|
7527
7737
|
}
|
|
7528
7738
|
//#endregion
|
|
7739
|
+
//#region src/gen/slide/objects/model3d.ts
|
|
7740
|
+
/** The `am3d` namespace, doubling as `a:graphicData@uri` and the `mc:Choice Requires` token's URI. */
|
|
7741
|
+
const AM3D_NS = "http://schemas.microsoft.com/office/drawing/2017/model3d";
|
|
7742
|
+
/** Denominator of every `am3d` rational element (`@n`/`@d`). */
|
|
7743
|
+
const RATIO_DEN = 1e6;
|
|
7744
|
+
/**
|
|
7745
|
+
* `am3d:raster@rName`/`@rVer` — the renderer that produced the cached preview. PowerPoint stamps
|
|
7746
|
+
* its own renderer here; ts-pptx did not rasterize anything, but the attributes are what PowerPoint
|
|
7747
|
+
* writes and the element is where the preview blip lives, so they are reproduced verbatim.
|
|
7748
|
+
*/
|
|
7749
|
+
const RASTER = {
|
|
7750
|
+
rName: "Office3DRenderer",
|
|
7751
|
+
rVer: "16.0.8326"
|
|
7752
|
+
};
|
|
7753
|
+
/**
|
|
7754
|
+
* `am3d:objViewport@viewportSz`. Bounding-box derived in PowerPoint's output (a cube and a slab
|
|
7755
|
+
* gave different values); the cube's is emitted, matching the fixed default camera.
|
|
7756
|
+
*/
|
|
7757
|
+
const OBJ_VIEWPORT_SZ = 3338805;
|
|
7758
|
+
/** The three point lights PowerPoint writes for every inserted model — key, fill and rim. */
|
|
7759
|
+
const PT_LIGHTS = [
|
|
7760
|
+
{
|
|
7761
|
+
clr: {
|
|
7762
|
+
r: 1e5,
|
|
7763
|
+
g: 75e3,
|
|
7764
|
+
b: 5e4
|
|
7765
|
+
},
|
|
7766
|
+
intensityN: 9765625,
|
|
7767
|
+
pos: {
|
|
7768
|
+
x: 21959998,
|
|
7769
|
+
y: 70920001,
|
|
7770
|
+
z: 16344003
|
|
7771
|
+
}
|
|
7772
|
+
},
|
|
7773
|
+
{
|
|
7774
|
+
clr: {
|
|
7775
|
+
r: 4e4,
|
|
7776
|
+
g: 6e4,
|
|
7777
|
+
b: 95e3
|
|
7778
|
+
},
|
|
7779
|
+
intensityN: 1225e4,
|
|
7780
|
+
pos: {
|
|
7781
|
+
x: -37964106,
|
|
7782
|
+
y: 51130435,
|
|
7783
|
+
z: 57631972
|
|
7784
|
+
}
|
|
7785
|
+
},
|
|
7786
|
+
{
|
|
7787
|
+
clr: {
|
|
7788
|
+
r: 86837,
|
|
7789
|
+
g: 72700,
|
|
7790
|
+
b: 1e5
|
|
7791
|
+
},
|
|
7792
|
+
intensityN: 3125e3,
|
|
7793
|
+
pos: {
|
|
7794
|
+
x: -37739122,
|
|
7795
|
+
y: 58056624,
|
|
7796
|
+
z: -34769649
|
|
7797
|
+
}
|
|
7798
|
+
}
|
|
7799
|
+
];
|
|
7800
|
+
/** `am3d:ambientLight` — neutral 50% scRGB at half illuminance, constant like the point lights. */
|
|
7801
|
+
const AMBIENT = {
|
|
7802
|
+
clr: {
|
|
7803
|
+
r: 5e4,
|
|
7804
|
+
g: 5e4,
|
|
7805
|
+
b: 5e4
|
|
7806
|
+
},
|
|
7807
|
+
illuminanceN: 5e5
|
|
7808
|
+
};
|
|
7809
|
+
/** `<am3d:clr><a:scrgbClr …/></am3d:clr>` — the colour wrapper both light kinds share. */
|
|
7810
|
+
function lightColor(clr) {
|
|
7811
|
+
return el("am3d:clr", null, raw(voidEl("a:scrgbClr", clr)));
|
|
7812
|
+
}
|
|
7813
|
+
/** The `am3d:camera` block: eye position, up vector, aim point and perspective fov. */
|
|
7814
|
+
function cameraEl(model) {
|
|
7815
|
+
return el("am3d:camera", null, [
|
|
7816
|
+
raw(voidEl("am3d:pos", model.pos)),
|
|
7817
|
+
raw(voidEl("am3d:up", model.up)),
|
|
7818
|
+
raw(voidEl("am3d:lookAt", model.lookAt)),
|
|
7819
|
+
raw(voidEl("am3d:perspective", { fov: model.fov }))
|
|
7820
|
+
]);
|
|
7821
|
+
}
|
|
7822
|
+
/**
|
|
7823
|
+
* The `am3d:trans` block: model-unit scale plus an identity placement. Only `meterPerModelUnit`
|
|
7824
|
+
* varies — `preTrans`/`scale`/`rot`/`postTrans` are the identity PowerPoint writes for a model
|
|
7825
|
+
* inserted without any subsequent 3D manipulation, and `am3d:rot` is emitted attribute-less.
|
|
7826
|
+
*/
|
|
7827
|
+
function transEl(model) {
|
|
7828
|
+
const unit = {
|
|
7829
|
+
n: RATIO_DEN,
|
|
7830
|
+
d: RATIO_DEN
|
|
7831
|
+
};
|
|
7832
|
+
return el("am3d:trans", null, [
|
|
7833
|
+
raw(voidEl("am3d:meterPerModelUnit", {
|
|
7834
|
+
n: model.meterPerModelUnitN,
|
|
7835
|
+
d: RATIO_DEN
|
|
7836
|
+
})),
|
|
7837
|
+
raw(voidEl("am3d:preTrans", {
|
|
7838
|
+
dx: 0,
|
|
7839
|
+
dy: 0,
|
|
7840
|
+
dz: 0
|
|
7841
|
+
})),
|
|
7842
|
+
raw(el("am3d:scale", null, [
|
|
7843
|
+
raw(voidEl("am3d:sx", unit)),
|
|
7844
|
+
raw(voidEl("am3d:sy", unit)),
|
|
7845
|
+
raw(voidEl("am3d:sz", unit))
|
|
7846
|
+
])),
|
|
7847
|
+
raw(voidEl("am3d:rot")),
|
|
7848
|
+
raw(voidEl("am3d:postTrans", {
|
|
7849
|
+
dx: 0,
|
|
7850
|
+
dy: 0,
|
|
7851
|
+
dz: 0
|
|
7852
|
+
}))
|
|
7853
|
+
]);
|
|
7854
|
+
}
|
|
7855
|
+
/** The fixed lighting rig: one ambient light and three point lights, in PowerPoint's order. */
|
|
7856
|
+
function lightsXml() {
|
|
7857
|
+
return el("am3d:ambientLight", null, [raw(lightColor(AMBIENT.clr)), raw(voidEl("am3d:illuminance", {
|
|
7858
|
+
n: AMBIENT.illuminanceN,
|
|
7859
|
+
d: RATIO_DEN
|
|
7860
|
+
}))]) + PT_LIGHTS.map((light) => el("am3d:ptLight", { rad: 0 }, [
|
|
7861
|
+
raw(lightColor(light.clr)),
|
|
7862
|
+
raw(voidEl("am3d:intensity", {
|
|
7863
|
+
n: light.intensityN,
|
|
7864
|
+
d: RATIO_DEN
|
|
7865
|
+
})),
|
|
7866
|
+
raw(voidEl("am3d:pos", light.pos))
|
|
7867
|
+
])).join("");
|
|
7868
|
+
}
|
|
7869
|
+
/** The `mc:Fallback` picture — the cached preview, drawn by everything that is not PowerPoint 2019+. */
|
|
7870
|
+
function fallbackPic(picId, objectName, altText, model, xf) {
|
|
7871
|
+
return el("p:pic", null, [
|
|
7872
|
+
raw(el("p:nvPicPr", null, [
|
|
7873
|
+
raw(cNvPrOpen(picId, objectName, altText) + "/>"),
|
|
7874
|
+
raw(el("p:cNvPicPr", null, raw(voidEl("a:picLocks", {
|
|
7875
|
+
noGrp: "1",
|
|
7876
|
+
noRot: "1",
|
|
7877
|
+
noChangeAspect: "1",
|
|
7878
|
+
noMove: "1",
|
|
7879
|
+
noResize: "1",
|
|
7880
|
+
noEditPoints: "1",
|
|
7881
|
+
noAdjustHandles: "1",
|
|
7882
|
+
noChangeArrowheads: "1",
|
|
7883
|
+
noChangeShapeType: "1",
|
|
7884
|
+
noCrop: "1"
|
|
7885
|
+
})))),
|
|
7886
|
+
raw(voidEl("p:nvPr"))
|
|
7887
|
+
])),
|
|
7888
|
+
raw(el("p:blipFill", null, [raw(voidEl("a:blip", { "r:embed": `rId${model.previewRid}` })), raw(el("a:stretch", null, raw(voidEl("a:fillRect"))))])),
|
|
7889
|
+
raw(el("p:spPr", null, [raw(el("a:xfrm", null, [raw(voidEl("a:off", {
|
|
7890
|
+
x: xf.x,
|
|
7891
|
+
y: xf.y
|
|
7892
|
+
})), raw(voidEl("a:ext", {
|
|
7893
|
+
cx: xf.cx,
|
|
7894
|
+
cy: xf.cy
|
|
7895
|
+
}))])), raw(el("a:prstGeom", { prst: "rect" }, raw(voidEl("a:avLst"))))]))
|
|
7896
|
+
]);
|
|
7897
|
+
}
|
|
7898
|
+
/**
|
|
7899
|
+
* Render a `model3d` slide object to its `<mc:AlternateContent>` XML. The `mc:Choice` carries the
|
|
7900
|
+
* real `<p:graphicFrame>` (the `am3d:model3d` graphicData PowerPoint 2019+ renders live); the
|
|
7901
|
+
* `mc:Fallback` carries the cached preview picture. See `gen/define/model3d.ts`.
|
|
7902
|
+
*/
|
|
7903
|
+
function renderModel3dObject(slideItemObj, idx, x, y, cx, cy) {
|
|
7904
|
+
const model = slideItemObj.model3d;
|
|
7905
|
+
if (!model) return "";
|
|
7906
|
+
const opts = slideItemObj.options || {};
|
|
7907
|
+
const altText = opts.altText || "";
|
|
7908
|
+
const spPr = el("am3d:spPr", null, [raw(el("a:xfrm", null, [raw(voidEl("a:off", {
|
|
7909
|
+
x: 0,
|
|
7910
|
+
y: 0
|
|
7911
|
+
})), raw(voidEl("a:ext", {
|
|
7912
|
+
cx,
|
|
7913
|
+
cy
|
|
7914
|
+
}))])), raw(el("a:prstGeom", { prst: "rect" }, raw(voidEl("a:avLst"))))]);
|
|
7915
|
+
const model3d = el("am3d:model3d", { "r:embed": `rId${model.modelRid}` }, [
|
|
7916
|
+
raw(spPr),
|
|
7917
|
+
raw(cameraEl(model)),
|
|
7918
|
+
raw(transEl(model)),
|
|
7919
|
+
raw(el("am3d:raster", RASTER, raw(voidEl("am3d:blip", { "r:embed": `rId${model.previewRid}` })))),
|
|
7920
|
+
raw(voidEl("am3d:objViewport", { viewportSz: OBJ_VIEWPORT_SZ })),
|
|
7921
|
+
raw(lightsXml())
|
|
7922
|
+
]);
|
|
7923
|
+
const graphicFrame = el("p:graphicFrame", null, [
|
|
7924
|
+
raw(el("p:nvGraphicFramePr", null, [
|
|
7925
|
+
raw(cNvPrOpen(idx + 2, opts.objectName, altText) + "/>"),
|
|
7926
|
+
raw(el("p:cNvGraphicFramePr", null, raw(voidEl("a:graphicFrameLocks")))),
|
|
7927
|
+
raw(voidEl("p:nvPr"))
|
|
7928
|
+
])),
|
|
7929
|
+
raw(el("p:xfrm", null, [raw(voidEl("a:off", {
|
|
7930
|
+
x,
|
|
7931
|
+
y
|
|
7932
|
+
})), raw(voidEl("a:ext", {
|
|
7933
|
+
cx,
|
|
7934
|
+
cy
|
|
7935
|
+
}))])),
|
|
7936
|
+
raw(el("a:graphic", null, raw(el("a:graphicData", { uri: AM3D_NS }, raw(model3d)))))
|
|
7937
|
+
]);
|
|
7938
|
+
return el("mc:AlternateContent", { "xmlns:mc": MC_NS }, [raw(el("mc:Choice", {
|
|
7939
|
+
"xmlns:am3d": AM3D_NS,
|
|
7940
|
+
Requires: "am3d"
|
|
7941
|
+
}, raw(graphicFrame))), raw(el("mc:Fallback", null, raw(fallbackPic(idx + 2, opts.objectName, altText, model, {
|
|
7942
|
+
x,
|
|
7943
|
+
y,
|
|
7944
|
+
cx,
|
|
7945
|
+
cy
|
|
7946
|
+
}))))]);
|
|
7947
|
+
}
|
|
7948
|
+
//#endregion
|
|
7529
7949
|
//#region src/gen/slide/objects/ole.ts
|
|
7530
7950
|
/** VML namespace — declared by an OLE object's `mc:Choice Requires="v"` (no VML content is emitted). */
|
|
7531
7951
|
const VML_NS = "urn:schemas-microsoft-com:vml";
|
|
@@ -7686,95 +8106,12 @@ function genTableCellBorderXml(cellBorder, diagonal) {
|
|
|
7686
8106
|
}
|
|
7687
8107
|
//#endregion
|
|
7688
8108
|
//#region src/gen/drawingml/table-cell3d.ts
|
|
7689
|
-
/** `ST_BevelPresetType`. */
|
|
7690
|
-
const BEVEL_PRESETS = [
|
|
7691
|
-
"relaxedInset",
|
|
7692
|
-
"circle",
|
|
7693
|
-
"slope",
|
|
7694
|
-
"cross",
|
|
7695
|
-
"angle",
|
|
7696
|
-
"softRound",
|
|
7697
|
-
"convex",
|
|
7698
|
-
"coolSlant",
|
|
7699
|
-
"divot",
|
|
7700
|
-
"riblet",
|
|
7701
|
-
"hardEdge",
|
|
7702
|
-
"artDeco"
|
|
7703
|
-
];
|
|
7704
|
-
/** `ST_PresetMaterialType`. */
|
|
7705
|
-
const MATERIALS = [
|
|
7706
|
-
"legacyMatte",
|
|
7707
|
-
"legacyPlastic",
|
|
7708
|
-
"legacyMetal",
|
|
7709
|
-
"legacyWireframe",
|
|
7710
|
-
"matte",
|
|
7711
|
-
"plastic",
|
|
7712
|
-
"metal",
|
|
7713
|
-
"warmMatte",
|
|
7714
|
-
"translucentPowder",
|
|
7715
|
-
"powder",
|
|
7716
|
-
"dkEdge",
|
|
7717
|
-
"softEdge",
|
|
7718
|
-
"clear",
|
|
7719
|
-
"flat",
|
|
7720
|
-
"softmetal"
|
|
7721
|
-
];
|
|
7722
|
-
/** `ST_LightRigType`. */
|
|
7723
|
-
const LIGHT_RIGS = [
|
|
7724
|
-
"legacyFlat1",
|
|
7725
|
-
"legacyFlat2",
|
|
7726
|
-
"legacyFlat3",
|
|
7727
|
-
"legacyFlat4",
|
|
7728
|
-
"legacyNormal1",
|
|
7729
|
-
"legacyNormal2",
|
|
7730
|
-
"legacyNormal3",
|
|
7731
|
-
"legacyNormal4",
|
|
7732
|
-
"legacyHarsh1",
|
|
7733
|
-
"legacyHarsh2",
|
|
7734
|
-
"legacyHarsh3",
|
|
7735
|
-
"legacyHarsh4",
|
|
7736
|
-
"threePt",
|
|
7737
|
-
"balanced",
|
|
7738
|
-
"soft",
|
|
7739
|
-
"harsh",
|
|
7740
|
-
"flood",
|
|
7741
|
-
"contrasting",
|
|
7742
|
-
"morning",
|
|
7743
|
-
"sunrise",
|
|
7744
|
-
"sunset",
|
|
7745
|
-
"chilly",
|
|
7746
|
-
"freezing",
|
|
7747
|
-
"flat",
|
|
7748
|
-
"twoPt",
|
|
7749
|
-
"glow",
|
|
7750
|
-
"brightRoom"
|
|
7751
|
-
];
|
|
7752
|
-
/** `ST_LightRigDirection`. */
|
|
7753
|
-
const LIGHT_DIRECTIONS = [
|
|
7754
|
-
"tl",
|
|
7755
|
-
"t",
|
|
7756
|
-
"tr",
|
|
7757
|
-
"l",
|
|
7758
|
-
"r",
|
|
7759
|
-
"bl",
|
|
7760
|
-
"b",
|
|
7761
|
-
"br"
|
|
7762
|
-
];
|
|
7763
8109
|
/**
|
|
7764
|
-
* Vet one enumerated value before it reaches the XML
|
|
7765
|
-
*
|
|
7766
|
-
* than as a mis-set option — so an unrecognized value is reported and the attribute dropped,
|
|
7767
|
-
* leaving the renderer on the schema default.
|
|
8110
|
+
* Vet one enumerated value before it reaches the XML, reporting and dropping anything outside
|
|
8111
|
+
* its `ST_` union. See `ooxml/check-enum.ts` for why the write path drops rather than throws.
|
|
7768
8112
|
*/
|
|
7769
8113
|
function resolveEnum(value, valid, field) {
|
|
7770
|
-
|
|
7771
|
-
if (valid.includes(value)) return value;
|
|
7772
|
-
warnOnce("table/invalid-cell3d", `table cell: cell3D \`${field}\` value \`${String(value)}\` is not valid and is ignored — use one of ${valid.join(", ")}.`, {
|
|
7773
|
-
received: value,
|
|
7774
|
-
field,
|
|
7775
|
-
valid
|
|
7776
|
-
});
|
|
7777
|
-
return null;
|
|
8114
|
+
return checkEnumOrWarn(value, valid, "table/invalid-cell3d", `table cell: cell3D \`${field}\``, { field });
|
|
7778
8115
|
}
|
|
7779
8116
|
/**
|
|
7780
8117
|
* A bevel dimension in EMU (`ST_PositiveCoordinate`), from a width in points.
|
|
@@ -7805,32 +8142,22 @@ function genTableCell3DXml(cell3D) {
|
|
|
7805
8142
|
prst: resolveEnum(cell3D.preset, BEVEL_PRESETS, "preset")
|
|
7806
8143
|
});
|
|
7807
8144
|
const rig = resolveEnum(cell3D.lightRig?.rig, LIGHT_RIGS, "lightRig.rig");
|
|
7808
|
-
const dir = resolveEnum(cell3D.lightRig?.dir,
|
|
8145
|
+
const dir = resolveEnum(cell3D.lightRig?.dir, LIGHT_RIG_DIRECTIONS, "lightRig.dir");
|
|
7809
8146
|
const lightRig = rig && dir ? voidEl("a:lightRig", {
|
|
7810
8147
|
rig,
|
|
7811
8148
|
dir
|
|
7812
8149
|
}) : "";
|
|
7813
8150
|
if (cell3D.lightRig && !lightRig) warnOnce("table/invalid-cell3d", "table cell: cell3D `lightRig` needs both `rig` and `dir` (both are required by CT_LightRig); the light rig is dropped and the bevel takes the renderer default.", { received: cell3D.lightRig });
|
|
7814
|
-
return el("a:cell3D", { prstMaterial: resolveEnum(cell3D.material,
|
|
8151
|
+
return el("a:cell3D", { prstMaterial: resolveEnum(cell3D.material, PRESET_MATERIALS, "material") }, [raw(bevel), lightRig ? raw(lightRig) : null]);
|
|
7815
8152
|
}
|
|
7816
8153
|
//#endregion
|
|
7817
8154
|
//#region src/gen/slide/objects/table.ts
|
|
7818
|
-
/** The two values `ST_TextHorzOverflowType` allows on `a:tcPr/@horzOverflow`. */
|
|
7819
|
-
const HORZ_OVERFLOW_VALUES = ["clip", "overflow"];
|
|
7820
8155
|
/**
|
|
7821
|
-
* Validate a cell's `horzOverflow` before it reaches the XML
|
|
7822
|
-
* `ST_TextHorzOverflowType`
|
|
7823
|
-
* reports that as a corrupt file, not as a mis-set option — so an unrecognized value is
|
|
7824
|
-
* reported and dropped instead of written. `undefined` (the common case) emits nothing.
|
|
8156
|
+
* Validate a cell's `horzOverflow` before it reaches the XML, reporting and dropping anything
|
|
8157
|
+
* outside `ST_TextHorzOverflowType`. `undefined` (the common case) emits nothing.
|
|
7825
8158
|
*/
|
|
7826
8159
|
function resolveHorzOverflow(value) {
|
|
7827
|
-
|
|
7828
|
-
if (HORZ_OVERFLOW_VALUES.includes(value)) return value;
|
|
7829
|
-
warnOnce("table/invalid-horz-overflow", `table cell: horzOverflow \`${String(value)}\` is not a valid value and is ignored — use ${HORZ_OVERFLOW_VALUES.join(" or ")}.`, {
|
|
7830
|
-
received: value,
|
|
7831
|
-
valid: HORZ_OVERFLOW_VALUES
|
|
7832
|
-
});
|
|
7833
|
-
return null;
|
|
8160
|
+
return checkEnumOrWarn(value, TEXT_HORZ_OVERFLOW, "table/invalid-horz-overflow", "table cell: horzOverflow");
|
|
7834
8161
|
}
|
|
7835
8162
|
/**
|
|
7836
8163
|
* Overlay `TableProps.outerBorder` onto one cell's own 4-side border tuple.
|
|
@@ -8295,7 +8622,6 @@ function renderZoomObject(slideItemObj, idx, x, y, cx, cy) {
|
|
|
8295
8622
|
}
|
|
8296
8623
|
//#endregion
|
|
8297
8624
|
//#region src/gen/slide/object.ts
|
|
8298
|
-
const PACKAGE_REL_NS$1 = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
8299
8625
|
/** The MS-2007 `media` rel that pairs with an ECMA audio/video/online rel on the same Target. */
|
|
8300
8626
|
const MS_MEDIA_REL = "http://schemas.microsoft.com/office/2007/relationships/media";
|
|
8301
8627
|
/** Slide→chartEx-part relationship type (MS, not the ECMA `.../relationships/chart`). */
|
|
@@ -8506,6 +8832,9 @@ function slideObjectToXml(slide) {
|
|
|
8506
8832
|
case "zoom":
|
|
8507
8833
|
strSlideXml += renderZoomObject(slideItemObj, idx, x, y, cx, cy);
|
|
8508
8834
|
break;
|
|
8835
|
+
case "model3d":
|
|
8836
|
+
strSlideXml += renderModel3dObject(slideItemObj, idx, x, y, cx, cy);
|
|
8837
|
+
break;
|
|
8509
8838
|
case "group": {
|
|
8510
8839
|
const groupChildren = slideItemObj._groupObjects || [];
|
|
8511
8840
|
let innerXml = "";
|
|
@@ -8654,12 +8983,12 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8654
8983
|
lastRid = Math.max(lastRid, rel.rId);
|
|
8655
8984
|
if (isHyperlinkRel(rel)) if (rel.data === "slide") rels.push(voidEl("Relationship", {
|
|
8656
8985
|
Id: `rId${rel.rId}`,
|
|
8657
|
-
Type: "
|
|
8986
|
+
Type: OFFICE_REL + "slide",
|
|
8658
8987
|
Target: `slide${rel.Target}.xml`
|
|
8659
8988
|
}));
|
|
8660
8989
|
else rels.push(voidEl("Relationship", {
|
|
8661
8990
|
Id: `rId${rel.rId}`,
|
|
8662
|
-
Type: "
|
|
8991
|
+
Type: OFFICE_REL + "hyperlink",
|
|
8663
8992
|
Target: rel.Target,
|
|
8664
8993
|
TargetMode: "External"
|
|
8665
8994
|
}));
|
|
@@ -8668,7 +8997,7 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8668
8997
|
lastRid = Math.max(lastRid, rel.rId);
|
|
8669
8998
|
rels.push(voidEl("Relationship", {
|
|
8670
8999
|
Id: `rId${rel.rId}`,
|
|
8671
|
-
Type: rel.isChartEx ? CHARTEX_REL : "
|
|
9000
|
+
Type: rel.isChartEx ? CHARTEX_REL : OFFICE_REL + "chart",
|
|
8672
9001
|
Target: rel.Target
|
|
8673
9002
|
}));
|
|
8674
9003
|
});
|
|
@@ -8683,10 +9012,11 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8683
9012
|
});
|
|
8684
9013
|
lastRid = Math.max(lastRid, rel.rId);
|
|
8685
9014
|
if (rel.oleRelType) rels.push(media(rel.oleRelType));
|
|
8686
|
-
else if (
|
|
8687
|
-
else if (relType.includes("
|
|
8688
|
-
else if (relType.includes("
|
|
8689
|
-
else if (relType.includes("
|
|
9015
|
+
else if (rel.model3dRelType) rels.push(media(rel.model3dRelType));
|
|
9016
|
+
else if (relType.includes("image")) rels.push(media(OFFICE_REL + "image"));
|
|
9017
|
+
else if (relType.includes("audio")) rels.push(hasTarget(relTarget) ? media(MS_MEDIA_REL) : media(OFFICE_REL + "audio"));
|
|
9018
|
+
else if (relType.includes("video")) rels.push(hasTarget(relTarget) ? media(MS_MEDIA_REL) : media(OFFICE_REL + "video"));
|
|
9019
|
+
else if (relType.includes("online")) rels.push(hasTarget(relTarget) ? media(MS_MEDIA_REL, "External") : media(OFFICE_REL + "video", "External"));
|
|
8690
9020
|
});
|
|
8691
9021
|
defaultRels.forEach((rel, idx) => {
|
|
8692
9022
|
rels.push(voidEl("Relationship", {
|
|
@@ -8695,7 +9025,7 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8695
9025
|
Target: rel.target
|
|
8696
9026
|
}));
|
|
8697
9027
|
});
|
|
8698
|
-
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS
|
|
9028
|
+
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, rels.map(raw));
|
|
8699
9029
|
}
|
|
8700
9030
|
//#endregion
|
|
8701
9031
|
//#region src/gen/slide/slide.ts
|
|
@@ -8773,7 +9103,6 @@ function getLayoutIdxForSlide(slides, slideLayouts, slideNumber) {
|
|
|
8773
9103
|
}
|
|
8774
9104
|
//#endregion
|
|
8775
9105
|
//#region src/gen/slide/notes.ts
|
|
8776
|
-
const PACKAGE_REL_NS = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
8777
9106
|
/**
|
|
8778
9107
|
* Collect the speaker-notes runs for a slide (flattened across any number of `addNotes()` calls).
|
|
8779
9108
|
* @param {PresSlideInternal} slide - the slide object
|
|
@@ -9257,19 +9586,19 @@ function makeXmlNotesSlide(slide) {
|
|
|
9257
9586
|
function makeXmlNotesSlideRel(slide, slideNumber) {
|
|
9258
9587
|
const hlinkRels = buildNotesSlideRels(slide).map((rel) => voidEl("Relationship", {
|
|
9259
9588
|
Id: `rId${rel.rId}`,
|
|
9260
|
-
Type: "
|
|
9589
|
+
Type: OFFICE_REL + "hyperlink",
|
|
9261
9590
|
Target: rel.Target,
|
|
9262
9591
|
TargetMode: "External"
|
|
9263
9592
|
})).join("");
|
|
9264
9593
|
return XML_DECL + el("Relationships", { xmlns: PACKAGE_REL_NS }, [
|
|
9265
9594
|
raw(voidEl("Relationship", {
|
|
9266
9595
|
Id: "rId1",
|
|
9267
|
-
Type: "
|
|
9596
|
+
Type: OFFICE_REL + "notesMaster",
|
|
9268
9597
|
Target: "../notesMasters/notesMaster1.xml"
|
|
9269
9598
|
})),
|
|
9270
9599
|
raw(voidEl("Relationship", {
|
|
9271
9600
|
Id: "rId2",
|
|
9272
|
-
Type: "
|
|
9601
|
+
Type: OFFICE_REL + "slide",
|
|
9273
9602
|
Target: `../slides/slide${slideNumber}.xml`
|
|
9274
9603
|
})),
|
|
9275
9604
|
raw(hlinkRels)
|
|
@@ -9286,7 +9615,7 @@ function makeXmlNotesSlideRel(slide, slideNumber) {
|
|
|
9286
9615
|
function makeXmlNotesMasterRel() {
|
|
9287
9616
|
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, raw(voidEl("Relationship", {
|
|
9288
9617
|
Id: "rId1",
|
|
9289
|
-
Type: "
|
|
9618
|
+
Type: OFFICE_REL + "theme",
|
|
9290
9619
|
Target: "../theme/theme2.xml"
|
|
9291
9620
|
})), {
|
|
9292
9621
|
childPrefix: "\n ",
|
|
@@ -9772,11 +10101,10 @@ function makeXmlCustomProperties(props) {
|
|
|
9772
10101
|
* Emit the package root relationships (app/core/presentation, plus custom-props
|
|
9773
10102
|
* when present).
|
|
9774
10103
|
*/
|
|
9775
|
-
const SCHEMA_BASE = "http://schemas.openxmlformats.org/";
|
|
9776
10104
|
function relationship$1(id, type, target) {
|
|
9777
10105
|
return voidEl("Relationship", {
|
|
9778
10106
|
Id: id,
|
|
9779
|
-
Type:
|
|
10107
|
+
Type: type,
|
|
9780
10108
|
Target: target
|
|
9781
10109
|
}, { openPrefix: "\n " });
|
|
9782
10110
|
}
|
|
@@ -9785,11 +10113,11 @@ function relationship$1(id, type, target) {
|
|
|
9785
10113
|
* @returns XML
|
|
9786
10114
|
*/
|
|
9787
10115
|
function makeXmlRootRels(hasCustomProps) {
|
|
9788
|
-
return XML_DECL + "\r\n" + el("Relationships", { xmlns:
|
|
9789
|
-
raw(relationship$1("rId1", "
|
|
9790
|
-
raw(relationship$1("rId2", "
|
|
9791
|
-
raw(relationship$1("rId3", "officeDocument
|
|
9792
|
-
hasCustomProps ? raw(relationship$1("rId4", "
|
|
10116
|
+
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, [
|
|
10117
|
+
raw(relationship$1("rId1", OFFICE_REL + "extended-properties", "docProps/app.xml")),
|
|
10118
|
+
raw(relationship$1("rId2", PACKAGE_REL_NS + "/metadata/core-properties", "docProps/core.xml")),
|
|
10119
|
+
raw(relationship$1("rId3", OFFICE_REL + "officeDocument", "ppt/presentation.xml")),
|
|
10120
|
+
hasCustomProps ? raw(relationship$1("rId4", OFFICE_REL + "custom-properties", "docProps/custom.xml")) : null
|
|
9793
10121
|
], { closePrefix: "\n " });
|
|
9794
10122
|
}
|
|
9795
10123
|
//#endregion
|
|
@@ -9829,13 +10157,13 @@ function presentationFontRelStart(slides) {
|
|
|
9829
10157
|
}
|
|
9830
10158
|
function makeXmlPresentationRels(slides, embeddedFonts) {
|
|
9831
10159
|
let intRelNum = 1;
|
|
9832
|
-
const rels = [relationship(1, "
|
|
9833
|
-
for (let idx = 1; idx <= slides.length; idx++) rels.push(relationship(++intRelNum, "
|
|
10160
|
+
const rels = [relationship(1, OFFICE_REL + "slideMaster", "slideMasters/slideMaster1.xml")];
|
|
10161
|
+
for (let idx = 1; idx <= slides.length; idx++) rels.push(relationship(++intRelNum, OFFICE_REL + "slide", `slides/slide${idx}.xml`));
|
|
9834
10162
|
intRelNum++;
|
|
9835
|
-
rels.push(relationship(intRelNum + 0, "
|
|
9836
|
-
if ((slides || []).some((slide) => (slide._comments || []).length > 0)) rels.push(relationship(intRelNum + 5, "
|
|
10163
|
+
rels.push(relationship(intRelNum + 0, OFFICE_REL + "notesMaster", "notesMasters/notesMaster1.xml"), relationship(intRelNum + 1, OFFICE_REL + "presProps", "presProps.xml"), relationship(intRelNum + 2, OFFICE_REL + "viewProps", "viewProps.xml"), relationship(intRelNum + 3, OFFICE_REL + "theme", "theme/theme1.xml"), relationship(intRelNum + 4, OFFICE_REL + "tableStyles", "tableStyles.xml"));
|
|
10164
|
+
if ((slides || []).some((slide) => (slide._comments || []).length > 0)) rels.push(relationship(intRelNum + 5, OFFICE_REL + "commentAuthors", "commentAuthors.xml"));
|
|
9837
10165
|
for (const face of flattenEmbeddedFaces(embeddedFonts || [], presentationFontRelStart(slides))) rels.push(relationship(face.rId, FONT_REL_TYPE, `fonts/font${face.partIndex}.fntdata`));
|
|
9838
|
-
return XML_DECL + "\r\n" + el("Relationships", { xmlns:
|
|
10166
|
+
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, rels.map(raw));
|
|
9839
10167
|
}
|
|
9840
10168
|
//#endregion
|
|
9841
10169
|
//#region src/gen/pres/presentation.ts
|
|
@@ -10563,18 +10891,14 @@ function createChartMediaRels(slide, zip, chartPromises) {
|
|
|
10563
10891
|
async function buildPackageParts(source, props) {
|
|
10564
10892
|
const pres = source.presentation;
|
|
10565
10893
|
const arrChartPromises = [];
|
|
10566
|
-
let arrMediaPromises = [];
|
|
10567
10894
|
const zip = new ZipWriter();
|
|
10568
10895
|
registerTransitionSounds(pres.slides);
|
|
10569
10896
|
const onMediaError = props.onMediaError ?? "throw";
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
|
|
10574
|
-
|
|
10575
|
-
});
|
|
10576
|
-
arrMediaPromises = arrMediaPromises.concat(encodeSlideMediaRels(pres.masterSlide, source.runtime, onMediaError));
|
|
10577
|
-
return await Promise.all(arrMediaPromises).then(async () => {
|
|
10897
|
+
return await encodeMediaForTargets([
|
|
10898
|
+
...pres.slides,
|
|
10899
|
+
...pres.slideLayouts,
|
|
10900
|
+
pres.masterSlide
|
|
10901
|
+
], source.runtime, onMediaError).then(async () => {
|
|
10578
10902
|
const canonicalMediaTargets = /* @__PURE__ */ new Map();
|
|
10579
10903
|
for (const target of [
|
|
10580
10904
|
...pres.slides,
|
|
@@ -10600,10 +10924,7 @@ async function buildPackageParts(source, props) {
|
|
|
10600
10924
|
rel.fileName = `${chartBase}.xml`;
|
|
10601
10925
|
rel.Target = `/ppt/charts/${chartBase}.xml`;
|
|
10602
10926
|
}
|
|
10603
|
-
pres.slides.
|
|
10604
|
-
if (slide._slideLayout) addPlaceholdersToSlideLayouts(slide);
|
|
10605
|
-
});
|
|
10606
|
-
applyMeasuredFit(pres.slides, source.fontMetrics);
|
|
10927
|
+
bakeSlideContent(pres.slides, source.fontMetrics);
|
|
10607
10928
|
const hasCustomProps = source.customProperties.length > 0;
|
|
10608
10929
|
zip.add("[Content_Types].xml", makeXmlContTypes(pres.slides, pres.slideLayouts, pres.masterSlide, hasCustomProps, pres.embeddedFonts));
|
|
10609
10930
|
zip.add("_rels/.rels", makeXmlRootRels(hasCustomProps));
|
|
@@ -10674,60 +10995,20 @@ async function writePackage(source, props) {
|
|
|
10674
10995
|
//#endregion
|
|
10675
10996
|
//#region src/presentation.ts
|
|
10676
10997
|
/**
|
|
10677
|
-
*
|
|
10678
|
-
*
|
|
10679
|
-
* TypeScript/ESM library that creates PowerPoint (pptx) presentations
|
|
10680
|
-
* https://github.com/gitbrent/PptxGenJS
|
|
10681
|
-
*
|
|
10682
|
-
* This framework is released under the MIT Public License (MIT)
|
|
10998
|
+
* ts-pptx: the presentation core
|
|
10683
10999
|
*
|
|
10684
|
-
*
|
|
11000
|
+
* Home of {@link PresentationCore}, the class every entry point subclasses with a runtime
|
|
11001
|
+
* adapter (`index.ts`, `node.ts`, `browser.ts`). See the class doc below for the layout of
|
|
11002
|
+
* its body and where package assembly actually happens.
|
|
10685
11003
|
*
|
|
10686
|
-
*
|
|
10687
|
-
*
|
|
11004
|
+
* Units: this library takes user coordinates in inches and converts to EMU on output — see
|
|
11005
|
+
* `units.ts` for the conversions and `STANDARD_LAYOUTS` for the built-in slide sizes.
|
|
10688
11006
|
*
|
|
10689
|
-
*
|
|
10690
|
-
*
|
|
10691
|
-
*
|
|
10692
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10693
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
10694
|
-
* furnished to do so, subject to the following conditions:
|
|
10695
|
-
*
|
|
10696
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
10697
|
-
* copies or substantial portions of the Software.
|
|
10698
|
-
*
|
|
10699
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
10700
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
10701
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
10702
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
10703
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
10704
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
10705
|
-
* SOFTWARE.
|
|
11007
|
+
* Derived from PptxGenJS (C) 2015-present Brent Ely (MIT), which in turn took some code from
|
|
11008
|
+
* the OfficeGen project (Copyright 2013 Ziv Barber). This project is likewise MIT; the full
|
|
11009
|
+
* license text is in `LICENSE` at the repository root.
|
|
10706
11010
|
*/
|
|
10707
|
-
|
|
10708
|
-
* Units of Measure used in PowerPoint documents
|
|
10709
|
-
*
|
|
10710
|
-
* PowerPoint (DrawingML) positions and sizes shapes in `EMU`; font sizing is in points.
|
|
10711
|
-
* This library takes user coordinates in inches and converts to EMU on output.
|
|
10712
|
-
* - 914400 EMUs is 1 inch
|
|
10713
|
-
* - 12700 EMUs is 1 point
|
|
10714
|
-
* - 72 points is 1 inch
|
|
10715
|
-
*
|
|
10716
|
-
* @see https://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/
|
|
10717
|
-
*/
|
|
10718
|
-
/**
|
|
10719
|
-
* Object Layouts
|
|
10720
|
-
*
|
|
10721
|
-
* - 16x9 (10" x 5.625")
|
|
10722
|
-
* - 16x10 (10" x 6.25")
|
|
10723
|
-
* - 4x3 (10" x 7.5")
|
|
10724
|
-
* - Wide (13.33" x 7.5")
|
|
10725
|
-
* - [custom] (any size)
|
|
10726
|
-
*
|
|
10727
|
-
* @see https://docs.microsoft.com/en-us/office/open-xml/structure-of-a-presentationml-document
|
|
10728
|
-
* @see https://docs.microsoft.com/en-us/previous-versions/office/developer/office-2010/hh273476(v=office.14)
|
|
10729
|
-
*/
|
|
10730
|
-
const VERSION = "2.0.0";
|
|
11011
|
+
const VERSION = "3.1.0";
|
|
10731
11012
|
function standardLayoutToPresLayout(layout) {
|
|
10732
11013
|
return {
|
|
10733
11014
|
name: layout.name,
|
|
@@ -11046,15 +11327,8 @@ var PresentationCore = class {
|
|
|
11046
11327
|
*/
|
|
11047
11328
|
extractSlides = async (opts = {}) => {
|
|
11048
11329
|
const onMediaError = opts.onMediaError ?? "throw";
|
|
11049
|
-
|
|
11050
|
-
this._slides.
|
|
11051
|
-
mediaPromises = mediaPromises.concat(encodeSlideMediaRels(slide, this._runtime, onMediaError));
|
|
11052
|
-
});
|
|
11053
|
-
await Promise.all(mediaPromises);
|
|
11054
|
-
this._slides.forEach((slide) => {
|
|
11055
|
-
if (slide._slideLayout) addPlaceholdersToSlideLayouts(slide);
|
|
11056
|
-
});
|
|
11057
|
-
applyMeasuredFit(this._slides, this._fontMetrics);
|
|
11330
|
+
await encodeMediaForTargets(this._slides, this._runtime, onMediaError);
|
|
11331
|
+
bakeSlideContent(this._slides, this._fontMetrics);
|
|
11058
11332
|
const slides = this._slides.map((slide) => {
|
|
11059
11333
|
const relByRid = new Map(slide._relsMedia.map((rel) => [rel.rId, rel]));
|
|
11060
11334
|
const avPreviewRids = /* @__PURE__ */ new Set();
|
|
@@ -11475,6 +11749,138 @@ var PresentationCore = class {
|
|
|
11475
11749
|
}
|
|
11476
11750
|
};
|
|
11477
11751
|
//#endregion
|
|
11752
|
+
//#region src/clip.ts
|
|
11753
|
+
const HALF_DISC = {
|
|
11754
|
+
deep: {
|
|
11755
|
+
topEdgeX: .31788,
|
|
11756
|
+
botEdgeX: .31788,
|
|
11757
|
+
tipTopX: .30061,
|
|
11758
|
+
tipTopY: .01078,
|
|
11759
|
+
tipBotX: .30061,
|
|
11760
|
+
tipBotY: .98922,
|
|
11761
|
+
apexY: .5,
|
|
11762
|
+
c1b: {
|
|
11763
|
+
x: .11594,
|
|
11764
|
+
y: .86833
|
|
11765
|
+
},
|
|
11766
|
+
c2b: {
|
|
11767
|
+
x: 0,
|
|
11768
|
+
y: .69392
|
|
11769
|
+
},
|
|
11770
|
+
c1t: {
|
|
11771
|
+
x: 0,
|
|
11772
|
+
y: .30609
|
|
11773
|
+
},
|
|
11774
|
+
c2t: {
|
|
11775
|
+
x: .11594,
|
|
11776
|
+
y: .13167
|
|
11777
|
+
}
|
|
11778
|
+
},
|
|
11779
|
+
shallow: {
|
|
11780
|
+
topEdgeX: .12611,
|
|
11781
|
+
botEdgeX: .11128,
|
|
11782
|
+
tipTopX: .09976,
|
|
11783
|
+
tipTopY: .05448,
|
|
11784
|
+
tipBotX: .09976,
|
|
11785
|
+
tipBotY: .97617,
|
|
11786
|
+
apexY: .51533,
|
|
11787
|
+
c1b: {
|
|
11788
|
+
x: .03522,
|
|
11789
|
+
y: .83247
|
|
11790
|
+
},
|
|
11791
|
+
c2b: {
|
|
11792
|
+
x: 0,
|
|
11793
|
+
y: .67725
|
|
11794
|
+
},
|
|
11795
|
+
c1t: {
|
|
11796
|
+
x: 0,
|
|
11797
|
+
y: .3534
|
|
11798
|
+
},
|
|
11799
|
+
c2t: {
|
|
11800
|
+
x: .03522,
|
|
11801
|
+
y: .19818
|
|
11802
|
+
}
|
|
11803
|
+
}
|
|
11804
|
+
};
|
|
11805
|
+
/**
|
|
11806
|
+
* Half-disc clip path for a `w × h` box. Authored flat-right; `flat: 'left'` mirrors `x → 1 - x`.
|
|
11807
|
+
*/
|
|
11808
|
+
function halfDisc(w, h, flat, preset) {
|
|
11809
|
+
const s = HALF_DISC[preset];
|
|
11810
|
+
const fx = flat === "left" ? (x) => (1 - x) * w : (x) => x * w;
|
|
11811
|
+
const fy = (y) => y * h;
|
|
11812
|
+
return [
|
|
11813
|
+
{
|
|
11814
|
+
x: fx(s.topEdgeX),
|
|
11815
|
+
y: fy(0),
|
|
11816
|
+
moveTo: true
|
|
11817
|
+
},
|
|
11818
|
+
{
|
|
11819
|
+
x: fx(1),
|
|
11820
|
+
y: fy(0)
|
|
11821
|
+
},
|
|
11822
|
+
{
|
|
11823
|
+
x: fx(1),
|
|
11824
|
+
y: fy(1)
|
|
11825
|
+
},
|
|
11826
|
+
{
|
|
11827
|
+
x: fx(s.botEdgeX),
|
|
11828
|
+
y: fy(1)
|
|
11829
|
+
},
|
|
11830
|
+
{
|
|
11831
|
+
x: fx(s.tipBotX),
|
|
11832
|
+
y: fy(s.tipBotY)
|
|
11833
|
+
},
|
|
11834
|
+
{
|
|
11835
|
+
x: fx(0),
|
|
11836
|
+
y: fy(s.apexY),
|
|
11837
|
+
curve: {
|
|
11838
|
+
type: "cubic",
|
|
11839
|
+
x1: fx(s.c1b.x),
|
|
11840
|
+
y1: fy(s.c1b.y),
|
|
11841
|
+
x2: fx(s.c2b.x),
|
|
11842
|
+
y2: fy(s.c2b.y)
|
|
11843
|
+
}
|
|
11844
|
+
},
|
|
11845
|
+
{
|
|
11846
|
+
x: fx(s.tipTopX),
|
|
11847
|
+
y: fy(s.tipTopY),
|
|
11848
|
+
curve: {
|
|
11849
|
+
type: "cubic",
|
|
11850
|
+
x1: fx(s.c1t.x),
|
|
11851
|
+
y1: fy(s.c1t.y),
|
|
11852
|
+
x2: fx(s.c2t.x),
|
|
11853
|
+
y2: fy(s.c2t.y)
|
|
11854
|
+
}
|
|
11855
|
+
},
|
|
11856
|
+
{ close: true }
|
|
11857
|
+
];
|
|
11858
|
+
}
|
|
11859
|
+
/**
|
|
11860
|
+
* Resolve a {@link ClipShape} to a freeform `points` path filling a `w × h` box, ready to hand
|
|
11861
|
+
* to `addImage({ points })`.
|
|
11862
|
+
*
|
|
11863
|
+
* `w`/`h` are the image box's size **in inches** and must match the `w`/`h` the picture is drawn
|
|
11864
|
+
* at — the path is emitted in the box's own coordinate space, not normalized (see the module
|
|
11865
|
+
* note above).
|
|
11866
|
+
* @param {ClipShape} shape - the named silhouette and its options
|
|
11867
|
+
* @param {number} w - image box width (inches)
|
|
11868
|
+
* @param {number} h - image box height (inches)
|
|
11869
|
+
* @returns {GeometryPoint[]} the freeform path, for `addImage({ points })`
|
|
11870
|
+
* @example
|
|
11871
|
+
* const w = 5.22, h = 7.5
|
|
11872
|
+
* slide.addImage({
|
|
11873
|
+
* path: 'cover.jpg', x: 0, y: 0, w, h,
|
|
11874
|
+
* points: clipPath({ kind: 'half-disc', flat: 'right' }, w, h),
|
|
11875
|
+
* sizing: { type: 'cover' }, // center-crop the photo into the "D"
|
|
11876
|
+
* })
|
|
11877
|
+
*/
|
|
11878
|
+
function clipPath(shape, w, h) {
|
|
11879
|
+
switch (shape.kind) {
|
|
11880
|
+
case "half-disc": return halfDisc(w, h, shape.flat, shape.preset ?? "deep");
|
|
11881
|
+
}
|
|
11882
|
+
}
|
|
11883
|
+
//#endregion
|
|
11478
11884
|
//#region src/types/text.ts
|
|
11479
11885
|
/** Factory for a single inline text run. Prevents `as never` casts when building mixed-style run arrays. */
|
|
11480
11886
|
function textRun(text, options) {
|
|
@@ -11488,6 +11894,6 @@ function textRuns(runs) {
|
|
|
11488
11894
|
return runs;
|
|
11489
11895
|
}
|
|
11490
11896
|
//#endregion
|
|
11491
|
-
export { textRuns as n,
|
|
11897
|
+
export { PresentationCore as i, textRuns as n, clipPath as r, textRun as t };
|
|
11492
11898
|
|
|
11493
|
-
//# sourceMappingURL=text-
|
|
11899
|
+
//# sourceMappingURL=text-B6PbMFih.js.map
|