@shbernal/ts-pptx 2.0.0 → 3.0.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 +7 -2
- package/dist/{autopage-tmfjRzL4.js → autopage-MxulehqQ.js} +3 -4
- package/dist/{autopage-tmfjRzL4.js.map → autopage-MxulehqQ.js.map} +1 -1
- package/dist/browser.d.ts +14 -6
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +12 -4
- package/dist/browser.js.map +1 -1
- package/dist/{diagnostics-CQ0JWc9m.d.ts → diagnostics-BqBTmA3a.d.ts} +95 -6
- package/dist/diagnostics-BqBTmA3a.d.ts.map +1 -0
- package/dist/{enums-D3aF4QGb.d.ts → enums-oLLeaSW3.d.ts} +2 -1
- package/dist/{enums-D3aF4QGb.d.ts.map → enums-oLLeaSW3.d.ts.map} +1 -1
- package/dist/{errors-B22h8Qd0.d.ts → errors-BENA-Xuw.d.ts} +3 -3
- package/dist/{errors-B22h8Qd0.d.ts.map → errors-BENA-Xuw.d.ts.map} +1 -1
- package/dist/{fit-BSWY0AYt.js → fit-DGSwMMNs.js} +0 -0
- package/dist/{fit-BSWY0AYt.js.map → fit-DGSwMMNs.js.map} +1 -1
- package/dist/{html-dom-BQLUntho.js → html-dom--J-Xuucf.js} +18 -4
- package/dist/html-dom--J-Xuucf.js.map +1 -0
- package/dist/html.d.ts +3 -3
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +6 -3
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +1 -1
- package/dist/inspect.js +2 -2
- package/dist/inspect.js.map +1 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.js.map +1 -1
- package/dist/measure.d.ts +2 -2
- package/dist/measure.js +1 -1
- package/dist/node.d.ts +14 -6
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +11 -3
- package/dist/node.js.map +1 -1
- package/dist/{pres-GU-jjBEx.d.ts → pres-2WsBGimU.d.ts} +3 -3
- package/dist/{pres-GU-jjBEx.d.ts.map → pres-2WsBGimU.d.ts.map} +1 -1
- package/dist/{presentation-CVaTZw1V.d.ts → presentation-CTVPpiwP.d.ts} +711 -582
- package/dist/presentation-CTVPpiwP.d.ts.map +1 -0
- package/dist/{presentation-MJe9WDi4.js → presentation-DAcOfzsP.js} +861 -341
- package/dist/presentation-DAcOfzsP.js.map +1 -0
- package/dist/read.d.ts +4 -4
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +2 -2
- 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-BWifcHDV.js} +670 -1034
- package/dist/shapes-BWifcHDV.js.map +1 -0
- package/dist/{slide-BBlElWr9.d.ts → slide-YuSCGa45.d.ts} +197 -22
- package/dist/slide-YuSCGa45.d.ts.map +1 -0
- package/dist/{image-size-C8uYE8GJ.js → st-enums-CgadEyPM.js} +233 -2
- package/dist/st-enums-CgadEyPM.js.map +1 -0
- package/dist/{text-B1ZrPEeK.js → text-120VFSDm.js} +717 -314
- package/dist/text-120VFSDm.js.map +1 -0
- package/dist/{units-internal-7JcMfYti.js → units-internal-CiFWZWk4.js} +2 -1
- package/dist/units-internal-CiFWZWk4.js.map +1 -0
- package/dist/zip.d.ts +2 -2
- package/dist/zip.js.map +1 -1
- package/package.json +30 -17
- package/dist/diagnostics-CQ0JWc9m.d.ts.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
2
|
import { n as InvalidOptionError, o as UnsupportedFeatureError, r as MediaError, t as InternalError } from "./errors-DGE9zh3U.js";
|
|
3
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-B-JUKwCS.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-
|
|
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-
|
|
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-CiFWZWk4.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-CgadEyPM.js";
|
|
6
|
+
import { t as getSlidesForTableRows } from "./autopage-MxulehqQ.js";
|
|
7
|
+
import { _ as parseFontMetrics, m as FontMetricsRegistry, n as measureText, r as computeTableLayout, t as applyMeasuredFit } from "./fit-DGSwMMNs.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
|
|
@@ -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
|
|
@@ -3104,23 +3234,6 @@ const BORDER_KEYS = [
|
|
|
3104
3234
|
"cap"
|
|
3105
3235
|
];
|
|
3106
3236
|
/**
|
|
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
3237
|
* Resolve the `a:prstDash/@val` a border should emit.
|
|
3125
3238
|
*
|
|
3126
3239
|
* `BorderProps.type` is a three-way switch, so on its own it can only say "dashed" and
|
|
@@ -3136,14 +3249,7 @@ const BORDER_DASH_VALUES = [
|
|
|
3136
3249
|
*/
|
|
3137
3250
|
function resolveBorderDash(border) {
|
|
3138
3251
|
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;
|
|
3252
|
+
return checkEnumOrWarn(border.dashType, PRESET_LINE_DASHES, "border/invalid-dash-type", "border: dashType") ?? fromType;
|
|
3147
3253
|
}
|
|
3148
3254
|
/**
|
|
3149
3255
|
* Report an authored key that is not part of `BorderProps`, which the library would
|
|
@@ -3585,7 +3691,34 @@ function makeSeriesDataPointsXml(chartType, obj, opts, varyColors) {
|
|
|
3585
3691
|
* gridlines, optional axis title -- but PowerPoint requires the child elements in a
|
|
3586
3692
|
* fixed order that differs per axis, so they stay as three separate builders rather
|
|
3587
3693
|
* than one parameterized one. Called by {@link ./chart-xml}'s axis region.
|
|
3588
|
-
|
|
3694
|
+
*
|
|
3695
|
+
* Sub-blocks are shared where they can be shared *exactly*: {@link axisLineSpPr} covers
|
|
3696
|
+
* `<c:spPr>`, which differs between the three only by indent width. `<c:txPr>` is
|
|
3697
|
+
* deliberately left duplicated — its inherited indentation is irregular *within* each copy
|
|
3698
|
+
* as well as between them (the category axis closes `</a:defRPr>` at three spaces, the value
|
|
3699
|
+
* axis at six), so parameterising it would take about as many indent arguments as it has
|
|
3700
|
+
* lines and would hide the quirks rather than share the structure.
|
|
3701
|
+
*/
|
|
3702
|
+
/**
|
|
3703
|
+
* The `<c:spPr>` axis-line block, identical in shape on all three axes.
|
|
3704
|
+
*
|
|
3705
|
+
* The only thing that differed between the three copies was how far each was indented — two
|
|
3706
|
+
* spaces on the category and series axes, one on the value axis — and that irregularity is
|
|
3707
|
+
* inherited, not meaningful. It is reproduced here rather than normalised because inter-element
|
|
3708
|
+
* whitespace being inert does not make changing it free: byte-identity is the gate that proves
|
|
3709
|
+
* an emitter refactor changed nothing, and it cannot tell a "harmless" whitespace edit from a
|
|
3710
|
+
* real one. `indent` keeps the quirk visible at the call site.
|
|
3711
|
+
* @param {number} indent - leading spaces on the `<c:spPr>` line; children step out by 2 and 4
|
|
3712
|
+
* @param {number} widthEmu - line width for `a:ln@w`
|
|
3713
|
+
* @param {boolean | undefined} show - false emits `<a:noFill/>` instead of a colour
|
|
3714
|
+
* @param {string | undefined} color - line colour, defaulting to {@link DEF_GRIDLINE_COLOR}
|
|
3715
|
+
* @param {string} dash - `a:prstDash@val`
|
|
3716
|
+
* @return {string} XML `<c:spPr>`
|
|
3717
|
+
*/
|
|
3718
|
+
function axisLineSpPr(indent, widthEmu, show, color, dash) {
|
|
3719
|
+
const at = (extra) => " ".repeat(indent + extra);
|
|
3720
|
+
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>`;
|
|
3721
|
+
}
|
|
3589
3722
|
function makeCatAxis(opts, axisId, valAxisId) {
|
|
3590
3723
|
let strXml = "";
|
|
3591
3724
|
const usesValueAxisForCategories = opts._type === "scatter" || opts._type === "bubble" || opts._type === "bubble3D";
|
|
@@ -3594,7 +3727,7 @@ function makeCatAxis(opts, axisId, valAxisId) {
|
|
|
3594
3727
|
else strXml += "<c:" + (opts.catLabelFormatCode ? "dateAx" : "catAx") + ">";
|
|
3595
3728
|
strXml += " <c:axId val=\"" + axisId + "\"/>";
|
|
3596
3729
|
strXml += " <c:scaling>";
|
|
3597
|
-
strXml += "<c:orientation val=\"" + (opts.catAxisOrientation ||
|
|
3730
|
+
strXml += "<c:orientation val=\"" + (opts.catAxisOrientation || "minMax") + "\"/>";
|
|
3598
3731
|
if (opts.catAxisMaxVal || opts.catAxisMaxVal === 0) strXml += `<c:max val="${opts.catAxisMaxVal}"/>`;
|
|
3599
3732
|
if (opts.catAxisMinVal || opts.catAxisMinVal === 0) strXml += `<c:min val="${opts.catAxisMinVal}"/>`;
|
|
3600
3733
|
strXml += "</c:scaling>";
|
|
@@ -3627,13 +3760,7 @@ function makeCatAxis(opts, axisId, valAxisId) {
|
|
|
3627
3760
|
strXml += " <c:minorTickMark val=\"" + (opts.catAxisMinorTickMark || "none") + "\"/>";
|
|
3628
3761
|
strXml += " <c:tickLblPos val=\"" + (opts.catAxisLabelPos || (opts.barDir === "col" ? "low" : "nextTo")) + "\"/>";
|
|
3629
3762
|
}
|
|
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>";
|
|
3763
|
+
strXml += axisLineSpPr(2, opts.catAxisLineSize ? valToPts(opts.catAxisLineSize) : EMU_PER_POINT, opts.catAxisLineShow, opts.catAxisLineColor, opts.catAxisLineStyle || "solid");
|
|
3637
3764
|
strXml += " <c:txPr>";
|
|
3638
3765
|
if (opts.catAxisLabelRotate) strXml += `<a:bodyPr rot="${convertRotationDegrees(opts.catAxisLabelRotate)}"/>`;
|
|
3639
3766
|
else strXml += "<a:bodyPr/>";
|
|
@@ -3697,7 +3824,7 @@ function makeValAxis(opts, valAxisId) {
|
|
|
3697
3824
|
strXml += " <c:axId val=\"" + valAxisId + "\"/>";
|
|
3698
3825
|
strXml += " <c:scaling>";
|
|
3699
3826
|
if (opts.valAxisLogScaleBase) strXml += `<c:logBase val="${opts.valAxisLogScaleBase}"/>`;
|
|
3700
|
-
strXml += "<c:orientation val=\"" + (opts.valAxisOrientation ||
|
|
3827
|
+
strXml += "<c:orientation val=\"" + (opts.valAxisOrientation || "minMax") + "\"/>";
|
|
3701
3828
|
if (opts.valAxisMaxVal || opts.valAxisMaxVal === 0) strXml += `<c:max val="${opts.valAxisMaxVal}"/>`;
|
|
3702
3829
|
if (opts.valAxisMinVal || opts.valAxisMinVal === 0) strXml += `<c:min val="${opts.valAxisMinVal}"/>`;
|
|
3703
3830
|
strXml += " </c:scaling>";
|
|
@@ -3724,13 +3851,7 @@ function makeValAxis(opts, valAxisId) {
|
|
|
3724
3851
|
strXml += " <c:minorTickMark val=\"" + (opts.valAxisMinorTickMark || "none") + "\"/>";
|
|
3725
3852
|
strXml += " <c:tickLblPos val=\"" + (opts.valAxisLabelPos || (opts.barDir === "col" ? "nextTo" : "low")) + "\"/>";
|
|
3726
3853
|
}
|
|
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>";
|
|
3854
|
+
strXml += axisLineSpPr(1, opts.valAxisLineSize ? valToPts(opts.valAxisLineSize) : EMU_PER_POINT, opts.valAxisLineShow, opts.valAxisLineColor, opts.valAxisLineStyle || "solid");
|
|
3734
3855
|
strXml += " <c:txPr>";
|
|
3735
3856
|
strXml += ` <a:bodyPr${opts.valAxisLabelRotate ? " rot=\"" + convertRotationDegrees(opts.valAxisLabelRotate).toString() + "\"" : ""}/>`;
|
|
3736
3857
|
strXml += " <a:lstStyle/>";
|
|
@@ -3765,7 +3886,7 @@ function makeSerAxis(opts, axisId, valAxisId) {
|
|
|
3765
3886
|
let strXml = "";
|
|
3766
3887
|
strXml += "<c:serAx>";
|
|
3767
3888
|
strXml += " <c:axId val=\"" + axisId + "\"/>";
|
|
3768
|
-
strXml += " <c:scaling><c:orientation val=\"" + (opts.serAxisOrientation ||
|
|
3889
|
+
strXml += " <c:scaling><c:orientation val=\"" + (opts.serAxisOrientation || "minMax") + "\"/></c:scaling>";
|
|
3769
3890
|
strXml += " <c:delete val=\"" + (opts.serAxisHidden ? "1" : "0") + "\"/>";
|
|
3770
3891
|
strXml += " <c:axPos val=\"" + (opts.barDir === "col" ? "b" : "l") + "\"/>";
|
|
3771
3892
|
strXml += opts.serGridLine && opts.serGridLine.style !== "none" ? createGridLineElement(opts.serGridLine) : "";
|
|
@@ -3783,13 +3904,7 @@ function makeSerAxis(opts, axisId, valAxisId) {
|
|
|
3783
3904
|
strXml += " <c:majorTickMark val=\"out\"/>";
|
|
3784
3905
|
strXml += " <c:minorTickMark val=\"none\"/>";
|
|
3785
3906
|
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>";
|
|
3907
|
+
strXml += axisLineSpPr(2, EMU_PER_POINT, opts.serAxisLineShow, opts.serAxisLineColor, "solid");
|
|
3793
3908
|
strXml += " <c:txPr>";
|
|
3794
3909
|
strXml += " <a:bodyPr/>";
|
|
3795
3910
|
strXml += " <a:lstStyle/>";
|
|
@@ -5139,7 +5254,8 @@ function chartExLayoutId(type) {
|
|
|
5139
5254
|
/**
|
|
5140
5255
|
* A deterministic `uniqueId` GUID for a `<cx:series>`, derived from the chart's package-global id.
|
|
5141
5256
|
* PowerPoint stamps a random GUID here; deriving it keeps output byte-stable (the project pins
|
|
5142
|
-
* chart determinism —
|
|
5257
|
+
* chart determinism — the package-wide id this derives from is assigned at write time in
|
|
5258
|
+
* `package/assemble.ts`, STEP 2). `seriesIdx`
|
|
5143
5259
|
* distinguishes multiple series within one chart (pareto emits two), varying the 4th GUID group so
|
|
5144
5260
|
* every series still gets a distinct id.
|
|
5145
5261
|
*/
|
|
@@ -5383,9 +5499,15 @@ function makeXmlChartEx(rel) {
|
|
|
5383
5499
|
* template — analogous to the default theme/worksheet boilerplate the library already embeds. They
|
|
5384
5500
|
* reference theme scheme colors, so they adapt to the deck theme without per-chart customization.
|
|
5385
5501
|
*/
|
|
5386
|
-
/**
|
|
5502
|
+
/**
|
|
5503
|
+
* The `cs:colorStyle` payload for a chartEx chart's `colors{N}.xml` part (theme-accent cycle).
|
|
5504
|
+
* @raw-xml-asset Captured verbatim from PowerPoint; not built here, so not a migration target.
|
|
5505
|
+
*/
|
|
5387
5506
|
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
|
-
/**
|
|
5507
|
+
/**
|
|
5508
|
+
* The `cs:chartStyle` payload for a chartEx chart's `style{N}.xml` part (PowerPoint default).
|
|
5509
|
+
* @raw-xml-asset Captured verbatim from PowerPoint; not built here, so not a migration target.
|
|
5510
|
+
*/
|
|
5389
5511
|
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
5512
|
/** Build the `ppt/charts/colors{N}.xml` part body. */
|
|
5391
5513
|
function makeChartExColorsXml() {
|
|
@@ -5397,7 +5519,6 @@ function makeChartExStyleXml() {
|
|
|
5397
5519
|
}
|
|
5398
5520
|
//#endregion
|
|
5399
5521
|
//#region src/gen/chart/embed-xlsx.ts
|
|
5400
|
-
const PACKAGE_REL_NS$2 = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
5401
5522
|
function relationship$2(id, type, target) {
|
|
5402
5523
|
return voidEl("Relationship", {
|
|
5403
5524
|
Id: id,
|
|
@@ -5407,7 +5528,7 @@ function relationship$2(id, type, target) {
|
|
|
5407
5528
|
}
|
|
5408
5529
|
/** `<Relationships>` wrapper shared by the workbook's `.rels` parts (all flat, no indent). */
|
|
5409
5530
|
function relationships(rels) {
|
|
5410
|
-
return el("Relationships", { xmlns: PACKAGE_REL_NS
|
|
5531
|
+
return el("Relationships", { xmlns: PACKAGE_REL_NS }, rels.map(raw));
|
|
5411
5532
|
}
|
|
5412
5533
|
/**
|
|
5413
5534
|
* Build the chart's embedded Excel workbook as a standalone OPC package and
|
|
@@ -5426,22 +5547,22 @@ function buildEmbeddedWorksheet(chartObject) {
|
|
|
5426
5547
|
const IS_MULTI_CAT_AXES = (data[0]?.labels?.length ?? 0) > 1;
|
|
5427
5548
|
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
5549
|
zipExcel.add("_rels/.rels", XML_DECL + relationships([
|
|
5429
|
-
relationship$2("rId1", "
|
|
5430
|
-
relationship$2("rId2", "
|
|
5431
|
-
relationship$2("rId3", "
|
|
5550
|
+
relationship$2("rId1", PACKAGE_REL_NS + "/metadata/core-properties", "docProps/core.xml"),
|
|
5551
|
+
relationship$2("rId2", OFFICE_REL + "extended-properties", "docProps/app.xml"),
|
|
5552
|
+
relationship$2("rId3", OFFICE_REL + "officeDocument", "xl/workbook.xml")
|
|
5432
5553
|
]) + "\n");
|
|
5433
5554
|
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
5555
|
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
5556
|
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", "
|
|
5557
|
+
relationship$2("rId3", OFFICE_REL + "styles", "styles.xml"),
|
|
5558
|
+
relationship$2("rId2", OFFICE_REL + "theme", "theme/theme1.xml"),
|
|
5559
|
+
relationship$2("rId1", OFFICE_REL + "worksheet", "worksheets/sheet1.xml"),
|
|
5560
|
+
relationship$2("rId4", OFFICE_REL + "sharedStrings", "sharedStrings.xml")
|
|
5440
5561
|
]));
|
|
5441
5562
|
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
5563
|
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
5564
|
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", "
|
|
5565
|
+
zipExcel.add("xl/worksheets/_rels/sheet1.xml.rels", XML_DECL + relationships([relationship$2("rId1", OFFICE_REL + "table", "../tables/table1.xml")]) + "\n");
|
|
5445
5566
|
zipExcel.add("xl/sharedStrings.xml", buildXlsxSharedStrings(chartObject, data, intBubbleCols, IS_MULTI_CAT_AXES));
|
|
5446
5567
|
zipExcel.add("xl/tables/table1.xml", buildXlsxTable(chartObject, data, intBubbleCols));
|
|
5447
5568
|
zipExcel.add("xl/worksheets/sheet1.xml", buildXlsxSheet(chartObject, data, intBubbleCols, IS_MULTI_CAT_AXES));
|
|
@@ -5622,7 +5743,7 @@ function buildXlsxSheet(chartObject, data, intBubbleCols, IS_MULTI_CAT_AXES) {
|
|
|
5622
5743
|
* @return {string} the chart part's `.rels` XML
|
|
5623
5744
|
*/
|
|
5624
5745
|
function buildChartRelsXml(embeddingTarget) {
|
|
5625
|
-
return XML_DECL + relationships([relationship$2("rId1", "
|
|
5746
|
+
return XML_DECL + relationships([relationship$2("rId1", OFFICE_REL + "package", embeddingTarget)]);
|
|
5626
5747
|
}
|
|
5627
5748
|
/**
|
|
5628
5749
|
* Build the `.rels` for a chartEx chart part: the embedded workbook (rId1, via `<cx:externalData>`)
|
|
@@ -5634,7 +5755,7 @@ function buildChartRelsXml(embeddingTarget) {
|
|
|
5634
5755
|
*/
|
|
5635
5756
|
function buildChartExRelsXml(embeddingTarget, colorsTarget, styleTarget) {
|
|
5636
5757
|
return XML_DECL + relationships([
|
|
5637
|
-
relationship$2("rId1", "
|
|
5758
|
+
relationship$2("rId1", OFFICE_REL + "package", embeddingTarget),
|
|
5638
5759
|
relationship$2("rId2", "http://schemas.microsoft.com/office/2011/relationships/chartColorStyle", colorsTarget),
|
|
5639
5760
|
relationship$2("rId3", "http://schemas.microsoft.com/office/2011/relationships/chartStyle", styleTarget)
|
|
5640
5761
|
]);
|
|
@@ -5752,6 +5873,63 @@ function encodeSlideMediaRels(layout, runtime, onMediaError = "throw") {
|
|
|
5752
5873
|
return imageProms;
|
|
5753
5874
|
}
|
|
5754
5875
|
//#endregion
|
|
5876
|
+
//#region src/gen/prepare.ts
|
|
5877
|
+
/**
|
|
5878
|
+
* ts-pptx: the pre-serialization pass
|
|
5879
|
+
*
|
|
5880
|
+
* Everything that must happen to authored slide state *before* any XML is built. Two callers
|
|
5881
|
+
* reach serialization and both need it:
|
|
5882
|
+
*
|
|
5883
|
+
* - `package/assemble.ts` — the normal `write`/`stream`/`writeFile` path, building a
|
|
5884
|
+
* complete `.pptx`.
|
|
5885
|
+
* - `PresentationCore.extractSlides()` — serializes slide bodies only, for splicing into
|
|
5886
|
+
* an already-loaded deck via `Presentation.appendSlides()` (`ts-pptx/read`).
|
|
5887
|
+
*
|
|
5888
|
+
* The second used to reimplement the first inline, kept in step by a comment that said
|
|
5889
|
+
* "exactly as ... does". Nothing failed when they drifted: `extractSlides` would simply emit
|
|
5890
|
+
* slides that did not match what a normal write produces, and no test compares the two.
|
|
5891
|
+
*
|
|
5892
|
+
* Two primitives rather than one combined pass, because the package path has work of its own
|
|
5893
|
+
* that must land *between* them: it de-duplicates identical media across the deck (which
|
|
5894
|
+
* needs the encoded bytes {@link encodeMediaForTargets} produces) and assigns package-unique
|
|
5895
|
+
* chart part filenames, both before any slide content is baked. Exposing the halves lets
|
|
5896
|
+
* `assemble` keep its established order exactly while still sharing the code.
|
|
5897
|
+
*
|
|
5898
|
+
* The order across the two is load-bearing:
|
|
5899
|
+
*
|
|
5900
|
+
* 1. **Media first.** It is the only asynchronous step, and the sync XML pass reads the
|
|
5901
|
+
* `rel.data` it populates.
|
|
5902
|
+
* 2. **Backfill placeholders**, so a slide inherits its layout's placeholder objects before
|
|
5903
|
+
* anything measures or serializes them.
|
|
5904
|
+
* 3. **Bake measured fit last**, because it measures the text step 2 may have just added and
|
|
5905
|
+
* writes the `fontScale` the sync XML pass then reads.
|
|
5906
|
+
*
|
|
5907
|
+
* The two functions take different target sets on purpose: media lives on layouts and the
|
|
5908
|
+
* master as well as on slides, while placeholder backfill and measured fit apply only to
|
|
5909
|
+
* slides. `extractSlides` passes only its slides to both, because it emits no layout or
|
|
5910
|
+
* master parts.
|
|
5911
|
+
*/
|
|
5912
|
+
/**
|
|
5913
|
+
* Step 1: load and base64-encode every media rel on the given targets, populating `rel.data`.
|
|
5914
|
+
* @param {ReadonlyArray<PresSlideInternal | SlideLayoutInternal>} targets - media-bearing targets (slides, layouts, master)
|
|
5915
|
+
* @param {RuntimeAdapter} runtime - runtime adapter used to load media
|
|
5916
|
+
* @param {'throw' | 'placeholder'} onMediaError - failure policy for unloadable media
|
|
5917
|
+
*/
|
|
5918
|
+
async function encodeMediaForTargets(targets, runtime, onMediaError) {
|
|
5919
|
+
const promises = [];
|
|
5920
|
+
for (const target of targets) promises.push(...encodeSlideMediaRels(target, runtime, onMediaError));
|
|
5921
|
+
await Promise.all(promises);
|
|
5922
|
+
}
|
|
5923
|
+
/**
|
|
5924
|
+
* Steps 2 and 3: backfill inherited layout placeholders, then bake measured text fit.
|
|
5925
|
+
* @param {PresSlideInternal[]} slides - the slides to prepare
|
|
5926
|
+
* @param {FontMetricsRegistry} fontMetrics - registered font metrics; an empty registry skips the fit bake
|
|
5927
|
+
*/
|
|
5928
|
+
function bakeSlideContent(slides, fontMetrics) {
|
|
5929
|
+
for (const slide of slides) if (slide._slideLayout) addPlaceholdersToSlideLayouts(slide);
|
|
5930
|
+
applyMeasuredFit(slides, fontMetrics);
|
|
5931
|
+
}
|
|
5932
|
+
//#endregion
|
|
5755
5933
|
//#region src/gen/slide/shape-ids.ts
|
|
5756
5934
|
/**
|
|
5757
5935
|
* Every object a slide renders, paired with the `<p:cNvPr>` id it is rendered with: top-level
|
|
@@ -6482,13 +6660,13 @@ function genXmlParagraphProperties(textObj, isDefault) {
|
|
|
6482
6660
|
const isPictureBullet = !!(bulletImage && (bulletImage.path || bulletImage.data));
|
|
6483
6661
|
if (opts.bullet?.indent) bulletMarL = valToPts(opts.bullet.indent);
|
|
6484
6662
|
if (opts.bullet.color && !isPictureBullet) strXmlBulletColor = el("a:buClr", null, raw(createColorElement(opts.bullet.color)));
|
|
6485
|
-
let bulletSizePct
|
|
6663
|
+
let bulletSizePct;
|
|
6486
6664
|
if (opts.bullet.size !== void 0) {
|
|
6487
6665
|
const bulletSize = Number(opts.bullet.size);
|
|
6488
6666
|
if (isNaN(bulletSize) || bulletSize < 25 || bulletSize > 400) warn("bullet/size-out-of-range", "`bullet.size` must be a percentage between 25 and 400!");
|
|
6489
6667
|
else bulletSizePct = Math.round(bulletSize * FIXED_PCT_PER_PERCENT);
|
|
6490
6668
|
}
|
|
6491
|
-
const strXmlBulletSize = voidEl("a:buSzPct", { val: bulletSizePct });
|
|
6669
|
+
const strXmlBulletSize = bulletSizePct === void 0 ? "" : voidEl("a:buSzPct", { val: bulletSizePct });
|
|
6492
6670
|
const strXmlBulletFont = opts.bullet.fontFace ? voidEl("a:buFont", { typeface: opts.bullet.fontFace }) : "";
|
|
6493
6671
|
const bulletIndentAttrs = () => ` marL="${opts.indentLevel && opts.indentLevel > 0 ? bulletMarL + bulletMarL * opts.indentLevel : bulletMarL}" indent="-${bulletMarL}"`;
|
|
6494
6672
|
if (isPictureBullet) {
|
|
@@ -6523,7 +6701,7 @@ function genXmlParagraphProperties(textObj, isDefault) {
|
|
|
6523
6701
|
}
|
|
6524
6702
|
} else if (opts.bullet) {
|
|
6525
6703
|
paragraphPropXml += ` marL="${opts.indentLevel && opts.indentLevel > 0 ? bulletMarL + bulletMarL * opts.indentLevel : bulletMarL}" indent="-${bulletMarL}"`;
|
|
6526
|
-
strXmlBullet =
|
|
6704
|
+
strXmlBullet = buChar("•");
|
|
6527
6705
|
} else if (!opts.bullet) {
|
|
6528
6706
|
paragraphPropXml += " indent=\"0\" marL=\"0\"";
|
|
6529
6707
|
strXmlBullet = voidEl("a:buNone");
|
|
@@ -7299,28 +7477,31 @@ function genXmlCustGeom(options, cx, cy, layout) {
|
|
|
7299
7477
|
* ts-pptx: DrawingML image sizing & cropping
|
|
7300
7478
|
*
|
|
7301
7479
|
* Build the `<a:srcRect>` (+ `<a:stretch>`) blipFill children for the image
|
|
7302
|
-
* sizing modes (`cover` / `contain` / `crop`)
|
|
7480
|
+
* sizing modes (`cover` / `contain` / `crop` / `stretch`), for the implicit
|
|
7481
|
+
* aspect-correct placement a vector source gets, and for explicit percentage crops.
|
|
7303
7482
|
*/
|
|
7304
7483
|
/** Every `<a:srcRect>` below is followed by this same fill directive. */
|
|
7305
7484
|
const STRETCH = el("a:stretch", null, raw(voidEl("a:fillRect")));
|
|
7485
|
+
/** The `<a:srcRect>` fitting `imgSize` into `boxDim`, followed by the fill directive. */
|
|
7486
|
+
function fitSrcRect(type, imgSize, boxDim) {
|
|
7487
|
+
const { l, r, t, b } = fitSrcRectPercents(type, imgSize, boxDim);
|
|
7488
|
+
return voidEl("a:srcRect", {
|
|
7489
|
+
l,
|
|
7490
|
+
r,
|
|
7491
|
+
t,
|
|
7492
|
+
b
|
|
7493
|
+
}) + STRETCH;
|
|
7494
|
+
}
|
|
7306
7495
|
const ImageSizingXml = {
|
|
7307
7496
|
cover: function(imgSize, boxDim) {
|
|
7308
|
-
|
|
7309
|
-
return voidEl("a:srcRect", {
|
|
7310
|
-
l,
|
|
7311
|
-
r,
|
|
7312
|
-
t,
|
|
7313
|
-
b
|
|
7314
|
-
}) + STRETCH;
|
|
7497
|
+
return fitSrcRect("cover", imgSize, boxDim);
|
|
7315
7498
|
},
|
|
7316
7499
|
contain: function(imgSize, boxDim) {
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
b
|
|
7323
|
-
}) + STRETCH;
|
|
7500
|
+
return fitSrcRect("contain", imgSize, boxDim);
|
|
7501
|
+
},
|
|
7502
|
+
/** No source rectangle at all: the image fills the box, aspect ratio be damned. */
|
|
7503
|
+
stretch: function() {
|
|
7504
|
+
return STRETCH;
|
|
7324
7505
|
},
|
|
7325
7506
|
crop: function(imgSize, boxDim) {
|
|
7326
7507
|
const l = boxDim.x;
|
|
@@ -7345,6 +7526,23 @@ const ImageSizingXml = {
|
|
|
7345
7526
|
}
|
|
7346
7527
|
};
|
|
7347
7528
|
/**
|
|
7529
|
+
* The blipFill children for a vector source the caller gave no `sizing` for: letterbox it to its
|
|
7530
|
+
* own aspect ratio inside its frame, the way `sizing: 'contain'` would — an SVG carries an
|
|
7531
|
+
* intrinsic ratio, and stretching a glyph into a box that disagrees with it is never the intent.
|
|
7532
|
+
*
|
|
7533
|
+
* Returns `null` when the two ratios already agree, which is the overwhelmingly common case (a
|
|
7534
|
+
* square icon in a square box). The caller then emits the plain `<a:stretch>` it always did, so
|
|
7535
|
+
* this default costs nothing — neither bytes nor a behaviour change — until it actually differs.
|
|
7536
|
+
* @param imgSize - the vector's intrinsic size (viewBox or width/height)
|
|
7537
|
+
* @param boxDim - the picture's displayed frame
|
|
7538
|
+
* @returns the `<a:srcRect>` + `<a:stretch>` children, or `null` if no letterboxing is needed
|
|
7539
|
+
*/
|
|
7540
|
+
function genXmlVectorAspectFit(imgSize, boxDim) {
|
|
7541
|
+
const { l, r, t, b } = fitSrcRectPercents("contain", imgSize, boxDim);
|
|
7542
|
+
if (l === 0 && r === 0 && t === 0 && b === 0) return null;
|
|
7543
|
+
return fitSrcRect("contain", imgSize, boxDim);
|
|
7544
|
+
}
|
|
7545
|
+
/**
|
|
7348
7546
|
* Build an explicit `<a:srcRect>` crop from percentage edge insets (0–100), emitted verbatim.
|
|
7349
7547
|
* Each inset is the percent of the *source* image trimmed from that edge; values serialize in
|
|
7350
7548
|
* 1000ths of a percent (DrawingML `ST_Percentage`, where 100% = 100000). Unlike `sizing: 'crop'`
|
|
@@ -7381,10 +7579,12 @@ function genXmlImageCrop(crop, objectName) {
|
|
|
7381
7579
|
function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, imgHeight, placeholderObj, locationAttrs, sizing, rounding) {
|
|
7382
7580
|
let strSlideXml = "";
|
|
7383
7581
|
slideItemObj.options = slideItemObj.options || {};
|
|
7582
|
+
const mediaRel = (slide._relsMedia || []).find((rel) => rel.rId === slideItemObj.imageRid);
|
|
7583
|
+
const relData = mediaRel?.data;
|
|
7584
|
+
const naturalSize = () => typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
7384
7585
|
if (slideItemObj.options._szAuto) {
|
|
7385
7586
|
const szAuto = slideItemObj.options._szAuto;
|
|
7386
|
-
const
|
|
7387
|
-
const natural = typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
7587
|
+
const natural = naturalSize();
|
|
7388
7588
|
if (natural) {
|
|
7389
7589
|
if (szAuto.w && szAuto.h) {
|
|
7390
7590
|
cx = pixelsToEmu(natural.w, 96);
|
|
@@ -7415,7 +7615,8 @@ function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, img
|
|
|
7415
7615
|
imgOpts.biLevel ? raw(voidEl("a:biLevel", { thresh: Math.round(imgOpts.biLevel.threshold * PERCENT_SCALE) })) : null
|
|
7416
7616
|
];
|
|
7417
7617
|
strSlideXml += "<p:blipFill>";
|
|
7418
|
-
|
|
7618
|
+
const isVector = mediaRel?.extn === "svg";
|
|
7619
|
+
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
7620
|
"xmlns:asvg": "http://schemas.microsoft.com/office/drawing/2016/SVG/main",
|
|
7420
7621
|
"r:embed": `rId${slideItemObj.imageRid}`
|
|
7421
7622
|
}, { openPrefix: " " })), {
|
|
@@ -7439,8 +7640,7 @@ function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, img
|
|
|
7439
7640
|
h: imgHeight
|
|
7440
7641
|
};
|
|
7441
7642
|
if (sizing.type === "cover" || sizing.type === "contain") {
|
|
7442
|
-
const
|
|
7443
|
-
const natural = typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
7643
|
+
const natural = naturalSize();
|
|
7444
7644
|
if (natural) cropSize = natural;
|
|
7445
7645
|
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
7646
|
}
|
|
@@ -7452,7 +7652,14 @@ function renderImageObject(slideItemObj, idx, slide, x, y, cx, cy, imgWidth, img
|
|
|
7452
7652
|
});
|
|
7453
7653
|
imgWidth = boxW;
|
|
7454
7654
|
imgHeight = boxH;
|
|
7455
|
-
} else
|
|
7655
|
+
} else {
|
|
7656
|
+
const natural = isVector ? naturalSize() : null;
|
|
7657
|
+
const aspectFit = natural ? genXmlVectorAspectFit(natural, {
|
|
7658
|
+
w: imgWidth,
|
|
7659
|
+
h: imgHeight
|
|
7660
|
+
}) : null;
|
|
7661
|
+
strSlideXml += aspectFit ?? el("a:stretch", null, raw(voidEl("a:fillRect")), { openPrefix: " " });
|
|
7662
|
+
}
|
|
7456
7663
|
strSlideXml += "</p:blipFill>";
|
|
7457
7664
|
strSlideXml += "<p:spPr>";
|
|
7458
7665
|
strSlideXml += el("a:xfrm", locationAttrs, [raw(voidEl("a:off", {
|
|
@@ -7526,6 +7733,216 @@ function renderMediaObject(slideItemObj, idx, x, y, cx, cy, locationAttrs) {
|
|
|
7526
7733
|
]);
|
|
7527
7734
|
}
|
|
7528
7735
|
//#endregion
|
|
7736
|
+
//#region src/gen/slide/objects/model3d.ts
|
|
7737
|
+
/** The `am3d` namespace, doubling as `a:graphicData@uri` and the `mc:Choice Requires` token's URI. */
|
|
7738
|
+
const AM3D_NS = "http://schemas.microsoft.com/office/drawing/2017/model3d";
|
|
7739
|
+
/** Denominator of every `am3d` rational element (`@n`/`@d`). */
|
|
7740
|
+
const RATIO_DEN = 1e6;
|
|
7741
|
+
/**
|
|
7742
|
+
* `am3d:raster@rName`/`@rVer` — the renderer that produced the cached preview. PowerPoint stamps
|
|
7743
|
+
* its own renderer here; ts-pptx did not rasterize anything, but the attributes are what PowerPoint
|
|
7744
|
+
* writes and the element is where the preview blip lives, so they are reproduced verbatim.
|
|
7745
|
+
*/
|
|
7746
|
+
const RASTER = {
|
|
7747
|
+
rName: "Office3DRenderer",
|
|
7748
|
+
rVer: "16.0.8326"
|
|
7749
|
+
};
|
|
7750
|
+
/**
|
|
7751
|
+
* `am3d:objViewport@viewportSz`. Bounding-box derived in PowerPoint's output (a cube and a slab
|
|
7752
|
+
* gave different values); the cube's is emitted, matching the fixed default camera.
|
|
7753
|
+
*/
|
|
7754
|
+
const OBJ_VIEWPORT_SZ = 3338805;
|
|
7755
|
+
/** The three point lights PowerPoint writes for every inserted model — key, fill and rim. */
|
|
7756
|
+
const PT_LIGHTS = [
|
|
7757
|
+
{
|
|
7758
|
+
clr: {
|
|
7759
|
+
r: 1e5,
|
|
7760
|
+
g: 75e3,
|
|
7761
|
+
b: 5e4
|
|
7762
|
+
},
|
|
7763
|
+
intensityN: 9765625,
|
|
7764
|
+
pos: {
|
|
7765
|
+
x: 21959998,
|
|
7766
|
+
y: 70920001,
|
|
7767
|
+
z: 16344003
|
|
7768
|
+
}
|
|
7769
|
+
},
|
|
7770
|
+
{
|
|
7771
|
+
clr: {
|
|
7772
|
+
r: 4e4,
|
|
7773
|
+
g: 6e4,
|
|
7774
|
+
b: 95e3
|
|
7775
|
+
},
|
|
7776
|
+
intensityN: 1225e4,
|
|
7777
|
+
pos: {
|
|
7778
|
+
x: -37964106,
|
|
7779
|
+
y: 51130435,
|
|
7780
|
+
z: 57631972
|
|
7781
|
+
}
|
|
7782
|
+
},
|
|
7783
|
+
{
|
|
7784
|
+
clr: {
|
|
7785
|
+
r: 86837,
|
|
7786
|
+
g: 72700,
|
|
7787
|
+
b: 1e5
|
|
7788
|
+
},
|
|
7789
|
+
intensityN: 3125e3,
|
|
7790
|
+
pos: {
|
|
7791
|
+
x: -37739122,
|
|
7792
|
+
y: 58056624,
|
|
7793
|
+
z: -34769649
|
|
7794
|
+
}
|
|
7795
|
+
}
|
|
7796
|
+
];
|
|
7797
|
+
/** `am3d:ambientLight` — neutral 50% scRGB at half illuminance, constant like the point lights. */
|
|
7798
|
+
const AMBIENT = {
|
|
7799
|
+
clr: {
|
|
7800
|
+
r: 5e4,
|
|
7801
|
+
g: 5e4,
|
|
7802
|
+
b: 5e4
|
|
7803
|
+
},
|
|
7804
|
+
illuminanceN: 5e5
|
|
7805
|
+
};
|
|
7806
|
+
/** `<am3d:clr><a:scrgbClr …/></am3d:clr>` — the colour wrapper both light kinds share. */
|
|
7807
|
+
function lightColor(clr) {
|
|
7808
|
+
return el("am3d:clr", null, raw(voidEl("a:scrgbClr", clr)));
|
|
7809
|
+
}
|
|
7810
|
+
/** The `am3d:camera` block: eye position, up vector, aim point and perspective fov. */
|
|
7811
|
+
function cameraEl(model) {
|
|
7812
|
+
return el("am3d:camera", null, [
|
|
7813
|
+
raw(voidEl("am3d:pos", model.pos)),
|
|
7814
|
+
raw(voidEl("am3d:up", model.up)),
|
|
7815
|
+
raw(voidEl("am3d:lookAt", model.lookAt)),
|
|
7816
|
+
raw(voidEl("am3d:perspective", { fov: model.fov }))
|
|
7817
|
+
]);
|
|
7818
|
+
}
|
|
7819
|
+
/**
|
|
7820
|
+
* The `am3d:trans` block: model-unit scale plus an identity placement. Only `meterPerModelUnit`
|
|
7821
|
+
* varies — `preTrans`/`scale`/`rot`/`postTrans` are the identity PowerPoint writes for a model
|
|
7822
|
+
* inserted without any subsequent 3D manipulation, and `am3d:rot` is emitted attribute-less.
|
|
7823
|
+
*/
|
|
7824
|
+
function transEl(model) {
|
|
7825
|
+
const unit = {
|
|
7826
|
+
n: RATIO_DEN,
|
|
7827
|
+
d: RATIO_DEN
|
|
7828
|
+
};
|
|
7829
|
+
return el("am3d:trans", null, [
|
|
7830
|
+
raw(voidEl("am3d:meterPerModelUnit", {
|
|
7831
|
+
n: model.meterPerModelUnitN,
|
|
7832
|
+
d: RATIO_DEN
|
|
7833
|
+
})),
|
|
7834
|
+
raw(voidEl("am3d:preTrans", {
|
|
7835
|
+
dx: 0,
|
|
7836
|
+
dy: 0,
|
|
7837
|
+
dz: 0
|
|
7838
|
+
})),
|
|
7839
|
+
raw(el("am3d:scale", null, [
|
|
7840
|
+
raw(voidEl("am3d:sx", unit)),
|
|
7841
|
+
raw(voidEl("am3d:sy", unit)),
|
|
7842
|
+
raw(voidEl("am3d:sz", unit))
|
|
7843
|
+
])),
|
|
7844
|
+
raw(voidEl("am3d:rot")),
|
|
7845
|
+
raw(voidEl("am3d:postTrans", {
|
|
7846
|
+
dx: 0,
|
|
7847
|
+
dy: 0,
|
|
7848
|
+
dz: 0
|
|
7849
|
+
}))
|
|
7850
|
+
]);
|
|
7851
|
+
}
|
|
7852
|
+
/** The fixed lighting rig: one ambient light and three point lights, in PowerPoint's order. */
|
|
7853
|
+
function lightsXml() {
|
|
7854
|
+
return el("am3d:ambientLight", null, [raw(lightColor(AMBIENT.clr)), raw(voidEl("am3d:illuminance", {
|
|
7855
|
+
n: AMBIENT.illuminanceN,
|
|
7856
|
+
d: RATIO_DEN
|
|
7857
|
+
}))]) + PT_LIGHTS.map((light) => el("am3d:ptLight", { rad: 0 }, [
|
|
7858
|
+
raw(lightColor(light.clr)),
|
|
7859
|
+
raw(voidEl("am3d:intensity", {
|
|
7860
|
+
n: light.intensityN,
|
|
7861
|
+
d: RATIO_DEN
|
|
7862
|
+
})),
|
|
7863
|
+
raw(voidEl("am3d:pos", light.pos))
|
|
7864
|
+
])).join("");
|
|
7865
|
+
}
|
|
7866
|
+
/** The `mc:Fallback` picture — the cached preview, drawn by everything that is not PowerPoint 2019+. */
|
|
7867
|
+
function fallbackPic(picId, objectName, altText, model, xf) {
|
|
7868
|
+
return el("p:pic", null, [
|
|
7869
|
+
raw(el("p:nvPicPr", null, [
|
|
7870
|
+
raw(cNvPrOpen(picId, objectName, altText) + "/>"),
|
|
7871
|
+
raw(el("p:cNvPicPr", null, raw(voidEl("a:picLocks", {
|
|
7872
|
+
noGrp: "1",
|
|
7873
|
+
noRot: "1",
|
|
7874
|
+
noChangeAspect: "1",
|
|
7875
|
+
noMove: "1",
|
|
7876
|
+
noResize: "1",
|
|
7877
|
+
noEditPoints: "1",
|
|
7878
|
+
noAdjustHandles: "1",
|
|
7879
|
+
noChangeArrowheads: "1",
|
|
7880
|
+
noChangeShapeType: "1",
|
|
7881
|
+
noCrop: "1"
|
|
7882
|
+
})))),
|
|
7883
|
+
raw(voidEl("p:nvPr"))
|
|
7884
|
+
])),
|
|
7885
|
+
raw(el("p:blipFill", null, [raw(voidEl("a:blip", { "r:embed": `rId${model.previewRid}` })), raw(el("a:stretch", null, raw(voidEl("a:fillRect"))))])),
|
|
7886
|
+
raw(el("p:spPr", null, [raw(el("a:xfrm", null, [raw(voidEl("a:off", {
|
|
7887
|
+
x: xf.x,
|
|
7888
|
+
y: xf.y
|
|
7889
|
+
})), raw(voidEl("a:ext", {
|
|
7890
|
+
cx: xf.cx,
|
|
7891
|
+
cy: xf.cy
|
|
7892
|
+
}))])), raw(el("a:prstGeom", { prst: "rect" }, raw(voidEl("a:avLst"))))]))
|
|
7893
|
+
]);
|
|
7894
|
+
}
|
|
7895
|
+
/**
|
|
7896
|
+
* Render a `model3d` slide object to its `<mc:AlternateContent>` XML. The `mc:Choice` carries the
|
|
7897
|
+
* real `<p:graphicFrame>` (the `am3d:model3d` graphicData PowerPoint 2019+ renders live); the
|
|
7898
|
+
* `mc:Fallback` carries the cached preview picture. See `gen/define/model3d.ts`.
|
|
7899
|
+
*/
|
|
7900
|
+
function renderModel3dObject(slideItemObj, idx, x, y, cx, cy) {
|
|
7901
|
+
const model = slideItemObj.model3d;
|
|
7902
|
+
if (!model) return "";
|
|
7903
|
+
const opts = slideItemObj.options || {};
|
|
7904
|
+
const altText = opts.altText || "";
|
|
7905
|
+
const spPr = el("am3d:spPr", null, [raw(el("a:xfrm", null, [raw(voidEl("a:off", {
|
|
7906
|
+
x: 0,
|
|
7907
|
+
y: 0
|
|
7908
|
+
})), raw(voidEl("a:ext", {
|
|
7909
|
+
cx,
|
|
7910
|
+
cy
|
|
7911
|
+
}))])), raw(el("a:prstGeom", { prst: "rect" }, raw(voidEl("a:avLst"))))]);
|
|
7912
|
+
const model3d = el("am3d:model3d", { "r:embed": `rId${model.modelRid}` }, [
|
|
7913
|
+
raw(spPr),
|
|
7914
|
+
raw(cameraEl(model)),
|
|
7915
|
+
raw(transEl(model)),
|
|
7916
|
+
raw(el("am3d:raster", RASTER, raw(voidEl("am3d:blip", { "r:embed": `rId${model.previewRid}` })))),
|
|
7917
|
+
raw(voidEl("am3d:objViewport", { viewportSz: OBJ_VIEWPORT_SZ })),
|
|
7918
|
+
raw(lightsXml())
|
|
7919
|
+
]);
|
|
7920
|
+
const graphicFrame = el("p:graphicFrame", null, [
|
|
7921
|
+
raw(el("p:nvGraphicFramePr", null, [
|
|
7922
|
+
raw(cNvPrOpen(idx + 2, opts.objectName, altText) + "/>"),
|
|
7923
|
+
raw(el("p:cNvGraphicFramePr", null, raw(voidEl("a:graphicFrameLocks")))),
|
|
7924
|
+
raw(voidEl("p:nvPr"))
|
|
7925
|
+
])),
|
|
7926
|
+
raw(el("p:xfrm", null, [raw(voidEl("a:off", {
|
|
7927
|
+
x,
|
|
7928
|
+
y
|
|
7929
|
+
})), raw(voidEl("a:ext", {
|
|
7930
|
+
cx,
|
|
7931
|
+
cy
|
|
7932
|
+
}))])),
|
|
7933
|
+
raw(el("a:graphic", null, raw(el("a:graphicData", { uri: AM3D_NS }, raw(model3d)))))
|
|
7934
|
+
]);
|
|
7935
|
+
return el("mc:AlternateContent", { "xmlns:mc": MC_NS }, [raw(el("mc:Choice", {
|
|
7936
|
+
"xmlns:am3d": AM3D_NS,
|
|
7937
|
+
Requires: "am3d"
|
|
7938
|
+
}, raw(graphicFrame))), raw(el("mc:Fallback", null, raw(fallbackPic(idx + 2, opts.objectName, altText, model, {
|
|
7939
|
+
x,
|
|
7940
|
+
y,
|
|
7941
|
+
cx,
|
|
7942
|
+
cy
|
|
7943
|
+
}))))]);
|
|
7944
|
+
}
|
|
7945
|
+
//#endregion
|
|
7529
7946
|
//#region src/gen/slide/objects/ole.ts
|
|
7530
7947
|
/** VML namespace — declared by an OLE object's `mc:Choice Requires="v"` (no VML content is emitted). */
|
|
7531
7948
|
const VML_NS = "urn:schemas-microsoft-com:vml";
|
|
@@ -7686,95 +8103,12 @@ function genTableCellBorderXml(cellBorder, diagonal) {
|
|
|
7686
8103
|
}
|
|
7687
8104
|
//#endregion
|
|
7688
8105
|
//#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
8106
|
/**
|
|
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.
|
|
8107
|
+
* Vet one enumerated value before it reaches the XML, reporting and dropping anything outside
|
|
8108
|
+
* its `ST_` union. See `ooxml/check-enum.ts` for why the write path drops rather than throws.
|
|
7768
8109
|
*/
|
|
7769
8110
|
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;
|
|
8111
|
+
return checkEnumOrWarn(value, valid, "table/invalid-cell3d", `table cell: cell3D \`${field}\``, { field });
|
|
7778
8112
|
}
|
|
7779
8113
|
/**
|
|
7780
8114
|
* A bevel dimension in EMU (`ST_PositiveCoordinate`), from a width in points.
|
|
@@ -7805,32 +8139,22 @@ function genTableCell3DXml(cell3D) {
|
|
|
7805
8139
|
prst: resolveEnum(cell3D.preset, BEVEL_PRESETS, "preset")
|
|
7806
8140
|
});
|
|
7807
8141
|
const rig = resolveEnum(cell3D.lightRig?.rig, LIGHT_RIGS, "lightRig.rig");
|
|
7808
|
-
const dir = resolveEnum(cell3D.lightRig?.dir,
|
|
8142
|
+
const dir = resolveEnum(cell3D.lightRig?.dir, LIGHT_RIG_DIRECTIONS, "lightRig.dir");
|
|
7809
8143
|
const lightRig = rig && dir ? voidEl("a:lightRig", {
|
|
7810
8144
|
rig,
|
|
7811
8145
|
dir
|
|
7812
8146
|
}) : "";
|
|
7813
8147
|
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,
|
|
8148
|
+
return el("a:cell3D", { prstMaterial: resolveEnum(cell3D.material, PRESET_MATERIALS, "material") }, [raw(bevel), lightRig ? raw(lightRig) : null]);
|
|
7815
8149
|
}
|
|
7816
8150
|
//#endregion
|
|
7817
8151
|
//#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
8152
|
/**
|
|
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.
|
|
8153
|
+
* Validate a cell's `horzOverflow` before it reaches the XML, reporting and dropping anything
|
|
8154
|
+
* outside `ST_TextHorzOverflowType`. `undefined` (the common case) emits nothing.
|
|
7825
8155
|
*/
|
|
7826
8156
|
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;
|
|
8157
|
+
return checkEnumOrWarn(value, TEXT_HORZ_OVERFLOW, "table/invalid-horz-overflow", "table cell: horzOverflow");
|
|
7834
8158
|
}
|
|
7835
8159
|
/**
|
|
7836
8160
|
* Overlay `TableProps.outerBorder` onto one cell's own 4-side border tuple.
|
|
@@ -8295,7 +8619,6 @@ function renderZoomObject(slideItemObj, idx, x, y, cx, cy) {
|
|
|
8295
8619
|
}
|
|
8296
8620
|
//#endregion
|
|
8297
8621
|
//#region src/gen/slide/object.ts
|
|
8298
|
-
const PACKAGE_REL_NS$1 = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
8299
8622
|
/** The MS-2007 `media` rel that pairs with an ECMA audio/video/online rel on the same Target. */
|
|
8300
8623
|
const MS_MEDIA_REL = "http://schemas.microsoft.com/office/2007/relationships/media";
|
|
8301
8624
|
/** Slide→chartEx-part relationship type (MS, not the ECMA `.../relationships/chart`). */
|
|
@@ -8506,6 +8829,9 @@ function slideObjectToXml(slide) {
|
|
|
8506
8829
|
case "zoom":
|
|
8507
8830
|
strSlideXml += renderZoomObject(slideItemObj, idx, x, y, cx, cy);
|
|
8508
8831
|
break;
|
|
8832
|
+
case "model3d":
|
|
8833
|
+
strSlideXml += renderModel3dObject(slideItemObj, idx, x, y, cx, cy);
|
|
8834
|
+
break;
|
|
8509
8835
|
case "group": {
|
|
8510
8836
|
const groupChildren = slideItemObj._groupObjects || [];
|
|
8511
8837
|
let innerXml = "";
|
|
@@ -8654,12 +8980,12 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8654
8980
|
lastRid = Math.max(lastRid, rel.rId);
|
|
8655
8981
|
if (isHyperlinkRel(rel)) if (rel.data === "slide") rels.push(voidEl("Relationship", {
|
|
8656
8982
|
Id: `rId${rel.rId}`,
|
|
8657
|
-
Type: "
|
|
8983
|
+
Type: OFFICE_REL + "slide",
|
|
8658
8984
|
Target: `slide${rel.Target}.xml`
|
|
8659
8985
|
}));
|
|
8660
8986
|
else rels.push(voidEl("Relationship", {
|
|
8661
8987
|
Id: `rId${rel.rId}`,
|
|
8662
|
-
Type: "
|
|
8988
|
+
Type: OFFICE_REL + "hyperlink",
|
|
8663
8989
|
Target: rel.Target,
|
|
8664
8990
|
TargetMode: "External"
|
|
8665
8991
|
}));
|
|
@@ -8668,7 +8994,7 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8668
8994
|
lastRid = Math.max(lastRid, rel.rId);
|
|
8669
8995
|
rels.push(voidEl("Relationship", {
|
|
8670
8996
|
Id: `rId${rel.rId}`,
|
|
8671
|
-
Type: rel.isChartEx ? CHARTEX_REL : "
|
|
8997
|
+
Type: rel.isChartEx ? CHARTEX_REL : OFFICE_REL + "chart",
|
|
8672
8998
|
Target: rel.Target
|
|
8673
8999
|
}));
|
|
8674
9000
|
});
|
|
@@ -8683,10 +9009,11 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8683
9009
|
});
|
|
8684
9010
|
lastRid = Math.max(lastRid, rel.rId);
|
|
8685
9011
|
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("
|
|
9012
|
+
else if (rel.model3dRelType) rels.push(media(rel.model3dRelType));
|
|
9013
|
+
else if (relType.includes("image")) rels.push(media(OFFICE_REL + "image"));
|
|
9014
|
+
else if (relType.includes("audio")) rels.push(hasTarget(relTarget) ? media(MS_MEDIA_REL) : media(OFFICE_REL + "audio"));
|
|
9015
|
+
else if (relType.includes("video")) rels.push(hasTarget(relTarget) ? media(MS_MEDIA_REL) : media(OFFICE_REL + "video"));
|
|
9016
|
+
else if (relType.includes("online")) rels.push(hasTarget(relTarget) ? media(MS_MEDIA_REL, "External") : media(OFFICE_REL + "video", "External"));
|
|
8690
9017
|
});
|
|
8691
9018
|
defaultRels.forEach((rel, idx) => {
|
|
8692
9019
|
rels.push(voidEl("Relationship", {
|
|
@@ -8695,7 +9022,7 @@ function slideObjectRelationsToXml(slide, defaultRels) {
|
|
|
8695
9022
|
Target: rel.target
|
|
8696
9023
|
}));
|
|
8697
9024
|
});
|
|
8698
|
-
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS
|
|
9025
|
+
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, rels.map(raw));
|
|
8699
9026
|
}
|
|
8700
9027
|
//#endregion
|
|
8701
9028
|
//#region src/gen/slide/slide.ts
|
|
@@ -8773,7 +9100,6 @@ function getLayoutIdxForSlide(slides, slideLayouts, slideNumber) {
|
|
|
8773
9100
|
}
|
|
8774
9101
|
//#endregion
|
|
8775
9102
|
//#region src/gen/slide/notes.ts
|
|
8776
|
-
const PACKAGE_REL_NS = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
8777
9103
|
/**
|
|
8778
9104
|
* Collect the speaker-notes runs for a slide (flattened across any number of `addNotes()` calls).
|
|
8779
9105
|
* @param {PresSlideInternal} slide - the slide object
|
|
@@ -9257,19 +9583,19 @@ function makeXmlNotesSlide(slide) {
|
|
|
9257
9583
|
function makeXmlNotesSlideRel(slide, slideNumber) {
|
|
9258
9584
|
const hlinkRels = buildNotesSlideRels(slide).map((rel) => voidEl("Relationship", {
|
|
9259
9585
|
Id: `rId${rel.rId}`,
|
|
9260
|
-
Type: "
|
|
9586
|
+
Type: OFFICE_REL + "hyperlink",
|
|
9261
9587
|
Target: rel.Target,
|
|
9262
9588
|
TargetMode: "External"
|
|
9263
9589
|
})).join("");
|
|
9264
9590
|
return XML_DECL + el("Relationships", { xmlns: PACKAGE_REL_NS }, [
|
|
9265
9591
|
raw(voidEl("Relationship", {
|
|
9266
9592
|
Id: "rId1",
|
|
9267
|
-
Type: "
|
|
9593
|
+
Type: OFFICE_REL + "notesMaster",
|
|
9268
9594
|
Target: "../notesMasters/notesMaster1.xml"
|
|
9269
9595
|
})),
|
|
9270
9596
|
raw(voidEl("Relationship", {
|
|
9271
9597
|
Id: "rId2",
|
|
9272
|
-
Type: "
|
|
9598
|
+
Type: OFFICE_REL + "slide",
|
|
9273
9599
|
Target: `../slides/slide${slideNumber}.xml`
|
|
9274
9600
|
})),
|
|
9275
9601
|
raw(hlinkRels)
|
|
@@ -9286,7 +9612,7 @@ function makeXmlNotesSlideRel(slide, slideNumber) {
|
|
|
9286
9612
|
function makeXmlNotesMasterRel() {
|
|
9287
9613
|
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, raw(voidEl("Relationship", {
|
|
9288
9614
|
Id: "rId1",
|
|
9289
|
-
Type: "
|
|
9615
|
+
Type: OFFICE_REL + "theme",
|
|
9290
9616
|
Target: "../theme/theme2.xml"
|
|
9291
9617
|
})), {
|
|
9292
9618
|
childPrefix: "\n ",
|
|
@@ -9772,11 +10098,10 @@ function makeXmlCustomProperties(props) {
|
|
|
9772
10098
|
* Emit the package root relationships (app/core/presentation, plus custom-props
|
|
9773
10099
|
* when present).
|
|
9774
10100
|
*/
|
|
9775
|
-
const SCHEMA_BASE = "http://schemas.openxmlformats.org/";
|
|
9776
10101
|
function relationship$1(id, type, target) {
|
|
9777
10102
|
return voidEl("Relationship", {
|
|
9778
10103
|
Id: id,
|
|
9779
|
-
Type:
|
|
10104
|
+
Type: type,
|
|
9780
10105
|
Target: target
|
|
9781
10106
|
}, { openPrefix: "\n " });
|
|
9782
10107
|
}
|
|
@@ -9785,11 +10110,11 @@ function relationship$1(id, type, target) {
|
|
|
9785
10110
|
* @returns XML
|
|
9786
10111
|
*/
|
|
9787
10112
|
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", "
|
|
10113
|
+
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, [
|
|
10114
|
+
raw(relationship$1("rId1", OFFICE_REL + "extended-properties", "docProps/app.xml")),
|
|
10115
|
+
raw(relationship$1("rId2", PACKAGE_REL_NS + "/metadata/core-properties", "docProps/core.xml")),
|
|
10116
|
+
raw(relationship$1("rId3", OFFICE_REL + "officeDocument", "ppt/presentation.xml")),
|
|
10117
|
+
hasCustomProps ? raw(relationship$1("rId4", OFFICE_REL + "custom-properties", "docProps/custom.xml")) : null
|
|
9793
10118
|
], { closePrefix: "\n " });
|
|
9794
10119
|
}
|
|
9795
10120
|
//#endregion
|
|
@@ -9829,13 +10154,13 @@ function presentationFontRelStart(slides) {
|
|
|
9829
10154
|
}
|
|
9830
10155
|
function makeXmlPresentationRels(slides, embeddedFonts) {
|
|
9831
10156
|
let intRelNum = 1;
|
|
9832
|
-
const rels = [relationship(1, "
|
|
9833
|
-
for (let idx = 1; idx <= slides.length; idx++) rels.push(relationship(++intRelNum, "
|
|
10157
|
+
const rels = [relationship(1, OFFICE_REL + "slideMaster", "slideMasters/slideMaster1.xml")];
|
|
10158
|
+
for (let idx = 1; idx <= slides.length; idx++) rels.push(relationship(++intRelNum, OFFICE_REL + "slide", `slides/slide${idx}.xml`));
|
|
9834
10159
|
intRelNum++;
|
|
9835
|
-
rels.push(relationship(intRelNum + 0, "
|
|
9836
|
-
if ((slides || []).some((slide) => (slide._comments || []).length > 0)) rels.push(relationship(intRelNum + 5, "
|
|
10160
|
+
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"));
|
|
10161
|
+
if ((slides || []).some((slide) => (slide._comments || []).length > 0)) rels.push(relationship(intRelNum + 5, OFFICE_REL + "commentAuthors", "commentAuthors.xml"));
|
|
9837
10162
|
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:
|
|
10163
|
+
return XML_DECL + "\r\n" + el("Relationships", { xmlns: PACKAGE_REL_NS }, rels.map(raw));
|
|
9839
10164
|
}
|
|
9840
10165
|
//#endregion
|
|
9841
10166
|
//#region src/gen/pres/presentation.ts
|
|
@@ -10563,18 +10888,14 @@ function createChartMediaRels(slide, zip, chartPromises) {
|
|
|
10563
10888
|
async function buildPackageParts(source, props) {
|
|
10564
10889
|
const pres = source.presentation;
|
|
10565
10890
|
const arrChartPromises = [];
|
|
10566
|
-
let arrMediaPromises = [];
|
|
10567
10891
|
const zip = new ZipWriter();
|
|
10568
10892
|
registerTransitionSounds(pres.slides);
|
|
10569
10893
|
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 () => {
|
|
10894
|
+
return await encodeMediaForTargets([
|
|
10895
|
+
...pres.slides,
|
|
10896
|
+
...pres.slideLayouts,
|
|
10897
|
+
pres.masterSlide
|
|
10898
|
+
], source.runtime, onMediaError).then(async () => {
|
|
10578
10899
|
const canonicalMediaTargets = /* @__PURE__ */ new Map();
|
|
10579
10900
|
for (const target of [
|
|
10580
10901
|
...pres.slides,
|
|
@@ -10600,10 +10921,7 @@ async function buildPackageParts(source, props) {
|
|
|
10600
10921
|
rel.fileName = `${chartBase}.xml`;
|
|
10601
10922
|
rel.Target = `/ppt/charts/${chartBase}.xml`;
|
|
10602
10923
|
}
|
|
10603
|
-
pres.slides.
|
|
10604
|
-
if (slide._slideLayout) addPlaceholdersToSlideLayouts(slide);
|
|
10605
|
-
});
|
|
10606
|
-
applyMeasuredFit(pres.slides, source.fontMetrics);
|
|
10924
|
+
bakeSlideContent(pres.slides, source.fontMetrics);
|
|
10607
10925
|
const hasCustomProps = source.customProperties.length > 0;
|
|
10608
10926
|
zip.add("[Content_Types].xml", makeXmlContTypes(pres.slides, pres.slideLayouts, pres.masterSlide, hasCustomProps, pres.embeddedFonts));
|
|
10609
10927
|
zip.add("_rels/.rels", makeXmlRootRels(hasCustomProps));
|
|
@@ -10674,60 +10992,20 @@ async function writePackage(source, props) {
|
|
|
10674
10992
|
//#endregion
|
|
10675
10993
|
//#region src/presentation.ts
|
|
10676
10994
|
/**
|
|
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)
|
|
10995
|
+
* ts-pptx: the presentation core
|
|
10683
10996
|
*
|
|
10684
|
-
*
|
|
10997
|
+
* Home of {@link PresentationCore}, the class every entry point subclasses with a runtime
|
|
10998
|
+
* adapter (`index.ts`, `node.ts`, `browser.ts`). See the class doc below for the layout of
|
|
10999
|
+
* its body and where package assembly actually happens.
|
|
10685
11000
|
*
|
|
10686
|
-
*
|
|
10687
|
-
*
|
|
11001
|
+
* Units: this library takes user coordinates in inches and converts to EMU on output — see
|
|
11002
|
+
* `units.ts` for the conversions and `STANDARD_LAYOUTS` for the built-in slide sizes.
|
|
10688
11003
|
*
|
|
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.
|
|
11004
|
+
* Derived from PptxGenJS (C) 2015-present Brent Ely (MIT), which in turn took some code from
|
|
11005
|
+
* the OfficeGen project (Copyright 2013 Ziv Barber). This project is likewise MIT; the full
|
|
11006
|
+
* license text is in `LICENSE` at the repository root.
|
|
10706
11007
|
*/
|
|
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";
|
|
11008
|
+
const VERSION = "3.0.0";
|
|
10731
11009
|
function standardLayoutToPresLayout(layout) {
|
|
10732
11010
|
return {
|
|
10733
11011
|
name: layout.name,
|
|
@@ -11046,15 +11324,8 @@ var PresentationCore = class {
|
|
|
11046
11324
|
*/
|
|
11047
11325
|
extractSlides = async (opts = {}) => {
|
|
11048
11326
|
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);
|
|
11327
|
+
await encodeMediaForTargets(this._slides, this._runtime, onMediaError);
|
|
11328
|
+
bakeSlideContent(this._slides, this._fontMetrics);
|
|
11058
11329
|
const slides = this._slides.map((slide) => {
|
|
11059
11330
|
const relByRid = new Map(slide._relsMedia.map((rel) => [rel.rId, rel]));
|
|
11060
11331
|
const avPreviewRids = /* @__PURE__ */ new Set();
|
|
@@ -11475,6 +11746,138 @@ var PresentationCore = class {
|
|
|
11475
11746
|
}
|
|
11476
11747
|
};
|
|
11477
11748
|
//#endregion
|
|
11749
|
+
//#region src/clip.ts
|
|
11750
|
+
const HALF_DISC = {
|
|
11751
|
+
deep: {
|
|
11752
|
+
topEdgeX: .31788,
|
|
11753
|
+
botEdgeX: .31788,
|
|
11754
|
+
tipTopX: .30061,
|
|
11755
|
+
tipTopY: .01078,
|
|
11756
|
+
tipBotX: .30061,
|
|
11757
|
+
tipBotY: .98922,
|
|
11758
|
+
apexY: .5,
|
|
11759
|
+
c1b: {
|
|
11760
|
+
x: .11594,
|
|
11761
|
+
y: .86833
|
|
11762
|
+
},
|
|
11763
|
+
c2b: {
|
|
11764
|
+
x: 0,
|
|
11765
|
+
y: .69392
|
|
11766
|
+
},
|
|
11767
|
+
c1t: {
|
|
11768
|
+
x: 0,
|
|
11769
|
+
y: .30609
|
|
11770
|
+
},
|
|
11771
|
+
c2t: {
|
|
11772
|
+
x: .11594,
|
|
11773
|
+
y: .13167
|
|
11774
|
+
}
|
|
11775
|
+
},
|
|
11776
|
+
shallow: {
|
|
11777
|
+
topEdgeX: .12611,
|
|
11778
|
+
botEdgeX: .11128,
|
|
11779
|
+
tipTopX: .09976,
|
|
11780
|
+
tipTopY: .05448,
|
|
11781
|
+
tipBotX: .09976,
|
|
11782
|
+
tipBotY: .97617,
|
|
11783
|
+
apexY: .51533,
|
|
11784
|
+
c1b: {
|
|
11785
|
+
x: .03522,
|
|
11786
|
+
y: .83247
|
|
11787
|
+
},
|
|
11788
|
+
c2b: {
|
|
11789
|
+
x: 0,
|
|
11790
|
+
y: .67725
|
|
11791
|
+
},
|
|
11792
|
+
c1t: {
|
|
11793
|
+
x: 0,
|
|
11794
|
+
y: .3534
|
|
11795
|
+
},
|
|
11796
|
+
c2t: {
|
|
11797
|
+
x: .03522,
|
|
11798
|
+
y: .19818
|
|
11799
|
+
}
|
|
11800
|
+
}
|
|
11801
|
+
};
|
|
11802
|
+
/**
|
|
11803
|
+
* Half-disc clip path for a `w × h` box. Authored flat-right; `flat: 'left'` mirrors `x → 1 - x`.
|
|
11804
|
+
*/
|
|
11805
|
+
function halfDisc(w, h, flat, preset) {
|
|
11806
|
+
const s = HALF_DISC[preset];
|
|
11807
|
+
const fx = flat === "left" ? (x) => (1 - x) * w : (x) => x * w;
|
|
11808
|
+
const fy = (y) => y * h;
|
|
11809
|
+
return [
|
|
11810
|
+
{
|
|
11811
|
+
x: fx(s.topEdgeX),
|
|
11812
|
+
y: fy(0),
|
|
11813
|
+
moveTo: true
|
|
11814
|
+
},
|
|
11815
|
+
{
|
|
11816
|
+
x: fx(1),
|
|
11817
|
+
y: fy(0)
|
|
11818
|
+
},
|
|
11819
|
+
{
|
|
11820
|
+
x: fx(1),
|
|
11821
|
+
y: fy(1)
|
|
11822
|
+
},
|
|
11823
|
+
{
|
|
11824
|
+
x: fx(s.botEdgeX),
|
|
11825
|
+
y: fy(1)
|
|
11826
|
+
},
|
|
11827
|
+
{
|
|
11828
|
+
x: fx(s.tipBotX),
|
|
11829
|
+
y: fy(s.tipBotY)
|
|
11830
|
+
},
|
|
11831
|
+
{
|
|
11832
|
+
x: fx(0),
|
|
11833
|
+
y: fy(s.apexY),
|
|
11834
|
+
curve: {
|
|
11835
|
+
type: "cubic",
|
|
11836
|
+
x1: fx(s.c1b.x),
|
|
11837
|
+
y1: fy(s.c1b.y),
|
|
11838
|
+
x2: fx(s.c2b.x),
|
|
11839
|
+
y2: fy(s.c2b.y)
|
|
11840
|
+
}
|
|
11841
|
+
},
|
|
11842
|
+
{
|
|
11843
|
+
x: fx(s.tipTopX),
|
|
11844
|
+
y: fy(s.tipTopY),
|
|
11845
|
+
curve: {
|
|
11846
|
+
type: "cubic",
|
|
11847
|
+
x1: fx(s.c1t.x),
|
|
11848
|
+
y1: fy(s.c1t.y),
|
|
11849
|
+
x2: fx(s.c2t.x),
|
|
11850
|
+
y2: fy(s.c2t.y)
|
|
11851
|
+
}
|
|
11852
|
+
},
|
|
11853
|
+
{ close: true }
|
|
11854
|
+
];
|
|
11855
|
+
}
|
|
11856
|
+
/**
|
|
11857
|
+
* Resolve a {@link ClipShape} to a freeform `points` path filling a `w × h` box, ready to hand
|
|
11858
|
+
* to `addImage({ points })`.
|
|
11859
|
+
*
|
|
11860
|
+
* `w`/`h` are the image box's size **in inches** and must match the `w`/`h` the picture is drawn
|
|
11861
|
+
* at — the path is emitted in the box's own coordinate space, not normalized (see the module
|
|
11862
|
+
* note above).
|
|
11863
|
+
* @param {ClipShape} shape - the named silhouette and its options
|
|
11864
|
+
* @param {number} w - image box width (inches)
|
|
11865
|
+
* @param {number} h - image box height (inches)
|
|
11866
|
+
* @returns {GeometryPoint[]} the freeform path, for `addImage({ points })`
|
|
11867
|
+
* @example
|
|
11868
|
+
* const w = 5.22, h = 7.5
|
|
11869
|
+
* slide.addImage({
|
|
11870
|
+
* path: 'cover.jpg', x: 0, y: 0, w, h,
|
|
11871
|
+
* points: clipPath({ kind: 'half-disc', flat: 'right' }, w, h),
|
|
11872
|
+
* sizing: { type: 'cover' }, // center-crop the photo into the "D"
|
|
11873
|
+
* })
|
|
11874
|
+
*/
|
|
11875
|
+
function clipPath(shape, w, h) {
|
|
11876
|
+
switch (shape.kind) {
|
|
11877
|
+
case "half-disc": return halfDisc(w, h, shape.flat, shape.preset ?? "deep");
|
|
11878
|
+
}
|
|
11879
|
+
}
|
|
11880
|
+
//#endregion
|
|
11478
11881
|
//#region src/types/text.ts
|
|
11479
11882
|
/** Factory for a single inline text run. Prevents `as never` casts when building mixed-style run arrays. */
|
|
11480
11883
|
function textRun(text, options) {
|
|
@@ -11488,6 +11891,6 @@ function textRuns(runs) {
|
|
|
11488
11891
|
return runs;
|
|
11489
11892
|
}
|
|
11490
11893
|
//#endregion
|
|
11491
|
-
export { textRuns as n,
|
|
11894
|
+
export { PresentationCore as i, textRuns as n, clipPath as r, textRun as t };
|
|
11492
11895
|
|
|
11493
|
-
//# sourceMappingURL=text-
|
|
11896
|
+
//# sourceMappingURL=text-120VFSDm.js.map
|