@shbernal/ts-pptx 4.1.0 → 5.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 +11 -11
- package/dist/anim-presets-Qbgh8uut.js +55 -0
- package/dist/anim-presets-Qbgh8uut.js.map +1 -0
- package/dist/{autopage-D4kyVp11.js → autopage-DqZ37VpL.js} +11 -12
- package/dist/autopage-DqZ37VpL.js.map +1 -0
- package/dist/{binary-string-CKVAYI3M.js → binary-string-Ba8VM3b9.js} +3 -4
- package/dist/binary-string-Ba8VM3b9.js.map +1 -0
- package/dist/{body-insets-kVHmjGc6.js → body-insets-BDHymJvz.js} +7 -9
- package/dist/body-insets-BDHymJvz.js.map +1 -0
- package/dist/browser.d.ts +24 -16
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +19 -19
- package/dist/browser.js.map +1 -1
- package/dist/{image-size-DwDbakcl.js → chart-metadata-CwiTTcJq.js} +576 -538
- package/dist/chart-metadata-CwiTTcJq.js.map +1 -0
- package/dist/{clip-DHDlnHUq.d.ts → clip-ISfCMtWA.d.ts} +6 -10
- package/dist/clip-ISfCMtWA.d.ts.map +1 -0
- package/dist/{notes-BcT571R4.js → comments-CKIZYRbZ.js} +517 -389
- package/dist/comments-CKIZYRbZ.js.map +1 -0
- package/dist/{diagnostics-DiMmBU8P.d.ts → diagnostics-MoA4MBq5.d.ts} +52 -50
- package/dist/diagnostics-MoA4MBq5.d.ts.map +1 -0
- package/dist/{embedded-fonts-CI_YGW2d.d.ts → embedded-fonts-U7HIIhPO.d.ts} +4 -6
- package/dist/embedded-fonts-U7HIIhPO.d.ts.map +1 -0
- package/dist/{entry-compose-6hF9aTmT.d.ts → entry-compose-CiakSt-f.d.ts} +53 -74
- package/dist/entry-compose-CiakSt-f.d.ts.map +1 -0
- package/dist/{errors-Da2nXCJm.js → entry-errors-JMthgJ2g.js} +41 -25
- package/dist/entry-errors-JMthgJ2g.js.map +1 -0
- package/dist/{table-cell-margins-PDshga8T.js → enums-BP9wsb9Q.js} +42 -45
- package/dist/enums-BP9wsb9Q.js.map +1 -0
- package/dist/{enums-DQRpVOLh.d.ts → enums-PcXr3o3J.d.ts} +11 -12
- package/dist/{enums-DQRpVOLh.d.ts.map → enums-PcXr3o3J.d.ts.map} +1 -1
- package/dist/families.d.ts +24 -26
- package/dist/families.d.ts.map +1 -1
- package/dist/families.js +3 -4
- package/dist/{fit-CcXbg__l.js → fit-Bpmzep6O.js} +60 -52
- package/dist/fit-Bpmzep6O.js.map +1 -0
- package/dist/{font-metrics-CBGmhLo0.d.ts → font-metrics-DTppw4t3.d.ts} +61 -37
- package/dist/font-metrics-DTppw4t3.d.ts.map +1 -0
- package/dist/{grid-9B2w5EaY.js → grid-DUIMxjfl.js} +23 -26
- package/dist/grid-DUIMxjfl.js.map +1 -0
- package/dist/{html-dom-DvJmuHt2.js → html-dom-LZCgntnJ.js} +42 -43
- package/dist/html-dom-LZCgntnJ.js.map +1 -0
- package/dist/html.d.ts +53 -9
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +12 -13
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +21 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -15
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +14 -16
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +18 -19
- package/dist/inspect.js.map +1 -1
- package/dist/{text-anchor-BgLPbwbL.js → lock-attrs-CSQnFDHP.js} +62 -12
- package/dist/lock-attrs-CSQnFDHP.js.map +1 -0
- package/dist/math.d.ts +2 -4
- package/dist/math.d.ts.map +1 -1
- package/dist/math.js +12 -13
- package/dist/math.js.map +1 -1
- package/dist/measure.d.ts +23 -12
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +3 -3
- package/dist/node.d.ts +21 -13
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +12 -12
- package/dist/node.js.map +1 -1
- package/dist/{options-internal-WqgMf720.js → options-internal-BWgmLPdx.js} +4 -5
- package/dist/options-internal-BWgmLPdx.js.map +1 -0
- package/dist/{package-KoEgVwII.d.ts → package-CANBWuSm.d.ts} +4 -12
- package/dist/package-CANBWuSm.d.ts.map +1 -0
- package/dist/{playbtn-CUqQdoDf.js → playbtn-BQZFJir9.js} +4 -5
- package/dist/playbtn-BQZFJir9.js.map +1 -0
- package/dist/{pres-BA9_lJbY.d.ts → pres-BkEkUAEM.d.ts} +383 -230
- package/dist/pres-BkEkUAEM.d.ts.map +1 -0
- package/dist/{presentation-Cyl74rq2.js → presentation-4Ggq0_Xa.js} +408 -288
- package/dist/presentation-4Ggq0_Xa.js.map +1 -0
- package/dist/{presentation-types-B3VQH4Bz.d.ts → presentation-types-BgnZR-0a.d.ts} +1104 -457
- package/dist/presentation-types-BgnZR-0a.d.ts.map +1 -0
- package/dist/read.d.ts +18 -13
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +4 -4
- package/dist/script.d.ts +116 -65
- package/dist/script.d.ts.map +1 -1
- package/dist/script.js +2697 -777
- package/dist/script.js.map +1 -1
- package/dist/{shapes-BcyFdZpp.js → shapes-CAPOjU0Q.js} +1556 -487
- package/dist/shapes-CAPOjU0Q.js.map +1 -0
- package/dist/{slide-BqPtyKmb.d.ts → slide-BmT4kMoO.d.ts} +94 -86
- package/dist/slide-BmT4kMoO.d.ts.map +1 -0
- package/dist/{slide-size-BalTjFuv.js → slide-size-SkScz1ig.js} +2 -3
- package/dist/{slide-size-BalTjFuv.js.map → slide-size-SkScz1ig.js.map} +1 -1
- package/dist/{table-dom-CVbvUfgh.js → table-dom-BYga4FYY.js} +3 -4
- package/dist/{table-dom-CVbvUfgh.js.map → table-dom-BYga4FYY.js.map} +1 -1
- package/dist/{text-BvFFMMFQ.js → text-Dz0ArGIp.js} +365 -318
- package/dist/text-Dz0ArGIp.js.map +1 -0
- package/dist/{transition-speed-kUEWDWTx.js → transition-speed-CNJ0fSpQ.js} +2 -3
- package/dist/{transition-speed-kUEWDWTx.js.map → transition-speed-CNJ0fSpQ.js.map} +1 -1
- package/dist/{units-internal-DFcUYjh3.js → units-internal-BR3a4cIi.js} +26 -29
- package/dist/units-internal-BR3a4cIi.js.map +1 -0
- package/dist/{zip-CYZ0F6BV.js → zip-7JTh61LX.js} +8 -10
- package/dist/zip-7JTh61LX.js.map +1 -0
- package/dist/{zip-CTll_dr0.d.ts → zip-uUjs9Cqx.d.ts} +4 -6
- package/dist/zip-uUjs9Cqx.d.ts.map +1 -0
- package/dist/zip.d.ts +3 -3
- package/dist/zip.js +3 -3
- package/dist/{zoom-BoNyOlPm.js → zoom-CSSeOwM8.js} +1153 -583
- package/dist/zoom-CSSeOwM8.js.map +1 -0
- package/package.json +20 -21
- package/skills/{ts-pptx-upstream → pptx-ts-upstream}/SKILL.md +27 -74
- package/dist/autopage-D4kyVp11.js.map +0 -1
- package/dist/binary-string-CKVAYI3M.js.map +0 -1
- package/dist/body-insets-kVHmjGc6.js.map +0 -1
- package/dist/clip-DHDlnHUq.d.ts.map +0 -1
- package/dist/diagnostics-DiMmBU8P.d.ts.map +0 -1
- package/dist/embedded-fonts-CI_YGW2d.d.ts.map +0 -1
- package/dist/entry-compose-6hF9aTmT.d.ts.map +0 -1
- package/dist/errors-Da2nXCJm.js.map +0 -1
- package/dist/fit-CcXbg__l.js.map +0 -1
- package/dist/font-metrics-CBGmhLo0.d.ts.map +0 -1
- package/dist/grid-9B2w5EaY.js.map +0 -1
- package/dist/html-dom-DvJmuHt2.js.map +0 -1
- package/dist/image-size-DwDbakcl.js.map +0 -1
- package/dist/notes-BcT571R4.js.map +0 -1
- package/dist/options-internal-WqgMf720.js.map +0 -1
- package/dist/package-KoEgVwII.d.ts.map +0 -1
- package/dist/playbtn-CUqQdoDf.js.map +0 -1
- package/dist/pres-BA9_lJbY.d.ts.map +0 -1
- package/dist/presentation-Cyl74rq2.js.map +0 -1
- package/dist/presentation-types-B3VQH4Bz.d.ts.map +0 -1
- package/dist/shapes-BcyFdZpp.js.map +0 -1
- package/dist/slide-BqPtyKmb.d.ts.map +0 -1
- package/dist/table-cell-margins-PDshga8T.js.map +0 -1
- package/dist/text-BvFFMMFQ.js.map +0 -1
- package/dist/text-anchor-BgLPbwbL.js.map +0 -1
- package/dist/units-internal-DFcUYjh3.js.map +0 -1
- package/dist/zip-CTll_dr0.d.ts.map +0 -1
- package/dist/zip-CYZ0F6BV.js.map +0 -1
- package/dist/zoom-BoNyOlPm.js.map +0 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A as DEF_CELL_BORDER, B as DEF_TEXT_SHADOW, C as usableTableWidthEmu, D as AXIS_ID_VALUE_PRIMARY, E as AXIS_ID_SERIES_PRIMARY, H as LETTERS, K as PIECHART_COLORS, L as DEF_SHAPE_SHADOW, M as DEF_CHART_GRIDLINE, N as DEF_FONT_COLOR, O as AXIS_ID_VALUE_SECONDARY, S as transparencyToAlpha, T as AXIS_ID_CATEGORY_SECONDARY, Z as ST_GUID, _ as resolveCellMarginsInches, b as resolveTableColWidthsEmu,
|
|
3
|
-
import { E as coordToEmu, F as EMU_PER_INCH, I as EMU_PER_POINT, M as pixelsToEmu,
|
|
4
|
-
import { $ as TICK_LABEL_POSITIONS,
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { n as setOrClear, t as pickDefined } from "./options-internal-
|
|
8
|
-
import { a as CELL_INHERITED_KEYS, i as computeTableLayout, n as measureText, r as requireBoxHeight } from "./fit-
|
|
9
|
-
import { r as PPTX_CONTENT_TYPE, t as ZipWriter } from "./zip-
|
|
10
|
-
import { a as
|
|
11
|
-
import { t as getSlidesForTableRows } from "./autopage-
|
|
12
|
-
|
|
1
|
+
import { d as warnOnce, n as InternalError, r as InvalidOptionError, s as UnsupportedFeatureError, u as warn } from "./entry-errors-JMthgJ2g.js";
|
|
2
|
+
import { A as DEF_CELL_BORDER, B as DEF_TEXT_SHADOW, C as usableTableWidthEmu, D as AXIS_ID_VALUE_PRIMARY, E as AXIS_ID_SERIES_PRIMARY, H as LETTERS, K as PIECHART_COLORS, L as DEF_SHAPE_SHADOW, M as DEF_CHART_GRIDLINE, N as DEF_FONT_COLOR, O as AXIS_ID_VALUE_SECONDARY, S as transparencyToAlpha, T as AXIS_ID_CATEGORY_SECONDARY, Z as ST_GUID, _ as resolveCellMarginsInches, b as resolveTableColWidthsEmu, d as marginToEmu, g as ptsToEmuLenient, j as DEF_CHART_BORDER, k as BARCHART_COLORS, l as lineWidthToEmu, n as clampRangedInput, o as fractionToFixedPercent, p as percentToFixedPercent, r as convertAngleUnits, s as getSmartParseNumber, u as mapStated, v as resolveInsetsEmu, w as AXIS_ID_CATEGORY_PRIMARY, x as resolveTableRowHeightEmu, y as resolveSlideMarginsInches } from "./units-internal-BR3a4cIi.js";
|
|
3
|
+
import { E as coordToEmu, F as EMU_PER_INCH, I as EMU_PER_POINT, M as pixelsToEmu, b as FIXED_PCT_PER_PERCENT, g as isChartType, h as isChartExType, i as ChartType, m as connectorPresetFor, o as PlaceholderType, p as asChartType, v as ANGLE_UNITS_PER_DEGREE, w as PERCENT_SCALE } from "./enums-BP9wsb9Q.js";
|
|
4
|
+
import { $t as TICK_LABEL_POSITIONS, At as LEGEND_POSITIONS, B as NOTES_SLIDE_CONTENT_TYPE, Bt as RADAR_STYLE_ALIASES, Dt as ERROR_BAR_TYPES, Et as ERROR_BAR_DIRECTIONS, G as PACKAGE_REL, H as OD_CONTENT, It as PLACEHOLDER_TYPES, Kt as TEXT_HORZ_OVERFLOW, M as IMAGE_REL, Mt as LIGHT_RIG_DIRECTIONS, N as MODEL3D_REL, Nt as LINE_DATA_SYMBOLS, O as EXTENDED_PROPS_CONTENT_TYPE, Ot as ERROR_BAR_VALUE_TYPES, R as NOTES_MASTER_CONTENT_TYPE, Rt as PRESET_MATERIALS, S as COMMENT_AUTHORS_CONTENT_TYPE, St as CROSS_BETWEEN, T as CORE_PROPS_REL, U as OFFICE_DOCUMENT_REL, Vt as RADAR_STYLE_ALIAS_NAMES, W as OFFICE_REL, X as RELATIONSHIPS_CONTENT_TYPE, Zt as TEXT_VERTICAL, _t as BAR_DIRECTIONS, an as checkEnumOrWarn, b as COMMENTS_CONTENT_TYPE, bt as BUILT_IN_UNITS, cn as xsdBoolIfTrue, dt as XLSX_CONTENT_TYPE, en as TICK_MARKS, f as CHARTEX_CONTENT_TYPE, ft as OOXML_NS, g as CHART_CONTENT_TYPE, gt as BAR_3D_SHAPES, h as CHART_COLOR_STYLE_REL, hn as svgMarkupToDataUri, ht as AXIS_ORIENTATIONS, i as getImageSizeFromBase64, jt as LIGHT_RIGS, k as EXTENDED_PROPS_REL, kt as GROUPINGS, m as CHART_COLOR_STYLE_CONTENT_TYPE, mn as hasBase64Header, mt as TABLE_GRAPHIC_DATA_URI, n as CHART_METADATA_NS, ot as THEME_CONTENT_TYPE, pn as decodeBase64ToBytes, qt as TEXT_SHAPE_TYPES, r as fitSrcRectPercents, sn as xsdBool, st as THEME_REL, t as CHART_METADATA_EXT_URI, tn as TIME_UNITS, v as CHART_STYLE_CONTENT_TYPE, vt as BAR_GROUPINGS, w as CORE_PROPS_CONTENT_TYPE, wt as DISPLAY_BLANKS_AS, y as CHART_STYLE_REL, yt as BEVEL_PRESETS, zt as RADAR_STYLES } from "./chart-metadata-CwiTTcJq.js";
|
|
5
|
+
import { a as TEXT_ANCHOR_BY_VALIGN, d as imageContentType, f as imageExtensionForSource, i as SHAPE_LOCK_ATTRS, r as PICTURE_LOCK_ATTRS, t as GRAPHIC_FRAME_LOCK_ATTRS } from "./lock-attrs-CSQnFDHP.js";
|
|
6
|
+
import { A as cNvPrEl, At as namedColorOr, B as genXmlCustGeom, Bt as getUuid, C as relsPath, Ct as resolveFillKind, Dt as alphaEl, Et as genXmlImageCropRect, F as previewPicBody, Ft as voidEl, G as groupRunsIntoLines, Gt as validateObjectName, H as prstGeomRect, I as slideTextColor, It as XML_DECL, J as clampFontSizeSz, K as renderTextParagraphsXml, Lt as bracedGuid, M as genXmlShapeLine, Mt as el, N as graphicFrameEl, Nt as elOrVoid, Ot as createColorElement, P as grpXfrmEl, Pt as raw, R as xfrmEl, S as overrideName, St as rejectEmptyFill, Tt as STRETCH_FILL_RECT, U as genXmlNormAutofit, Ut as nextMediaTarget, V as genXmlPresetGeom, W as genXmlParagraphProperties, Wt as preencodedPath, a as makeXmlNotesMaster, at as createLineCap, bt as genXmlColorSelection, c as makeXmlNotesSlideRel, ct as resolveDash, dt as withLineDefaults, ft as createShadowEffectLst, g as NOTES_MASTER_PATH, i as buildNotesSlideRels, it as borderLine, j as cNvPrHyperlink, jt as rejectEmptyColor, k as FALLBACK_PICTURE_LOCKS, kt as isColorValue, lt as strokeDash, m as relationshipsEl, n as makeXmlComments, nt as registerHyperlinkRel, o as makeXmlNotesMasterRel, ot as noStrokeLine, p as relationshipEl, pt as normalizeShadowOptions, r as resolveCommentAuthors, rt as validateHyperlink, s as makeXmlNotesSlide, st as resolveBorderDash, t as makeXmlCommentAuthors, tt as createHyperlinkRels, ut as strokePaint, x as notesSlidePath, xt as genXmlPatternFill, y as commentPath, z as assertKnownPreset, zt as getNewRelId } from "./comments-CKIZYRbZ.js";
|
|
7
|
+
import { n as setOrClear, t as pickDefined } from "./options-internal-BWgmLPdx.js";
|
|
8
|
+
import { a as CELL_INHERITED_KEYS, i as computeTableLayout, n as measureText, r as requireBoxHeight } from "./fit-Bpmzep6O.js";
|
|
9
|
+
import { r as PPTX_CONTENT_TYPE, t as ZipWriter } from "./zip-7JTh61LX.js";
|
|
10
|
+
import { a as cellHasHyperlink, n as tableColCount, o as resolveSpan, r as walkTableGrid, s as withCheckedSpans } from "./grid-DUIMxjfl.js";
|
|
11
|
+
import { t as getSlidesForTableRows } from "./autopage-DqZ37VpL.js";
|
|
12
|
+
// src/gen/define/image-rel.ts
|
|
13
13
|
/**
|
|
14
14
|
* Resolve a caller's `{ path, data }` to the source an image media rel is registered from, or say
|
|
15
15
|
* why there is none.
|
|
@@ -69,7 +69,7 @@ function pushMediaRel(target, source) {
|
|
|
69
69
|
/**
|
|
70
70
|
* Push an image media rel onto `target`, reusing an identical source's package part.
|
|
71
71
|
*
|
|
72
|
-
* Three definers need it
|
|
72
|
+
* Three definers need it: an image *fill* on a shape or text box (`registerImageFillMedia`), an
|
|
73
73
|
* `addImage()` raster (`addImageDefinition`), and the cached preview raster a Zoom tile, an OLE
|
|
74
74
|
* object or a 3D model is drawn from (`registerPreviewImage`). See {@link MediaRelSource.dedupe} for the match.
|
|
75
75
|
* @param target - slide (or layout/master) the rel is registered on
|
|
@@ -81,8 +81,8 @@ function registerImageMediaRel(target, source, relId) {
|
|
|
81
81
|
kind: "image",
|
|
82
82
|
extn: source.extn,
|
|
83
83
|
type: imageContentType(source.extn),
|
|
84
|
-
path: source.path
|
|
85
|
-
data: source.data
|
|
84
|
+
path: source.path,
|
|
85
|
+
data: source.data,
|
|
86
86
|
rId: relId,
|
|
87
87
|
dedupe: true
|
|
88
88
|
});
|
|
@@ -140,17 +140,16 @@ function registerSvgImageRels(target, source, pinned) {
|
|
|
140
140
|
svgRid
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
|
-
|
|
144
|
-
//#region src/gen/define/object-name.ts
|
|
143
|
+
// src/gen/define/object-name.ts
|
|
145
144
|
/**
|
|
146
|
-
* Take the next slide-wide index for `type`'s default Selection Pane name
|
|
145
|
+
* Take the next slide-wide index for `type`'s default Selection Pane name: 0-based here, and
|
|
147
146
|
* offset to the 1-based name by {@link resolveObjectName}.
|
|
148
147
|
*
|
|
149
148
|
* Default names used to be derived by counting the matching objects already in
|
|
150
149
|
* `target._slideObjects`. `buildGroupObject` splices group children back out of that array, so the
|
|
151
150
|
* count never advanced past them and a later top-level object reused a grouped child's name. This
|
|
152
151
|
* counter is immune to the splice: every object of a kind consumes an index when it is added,
|
|
153
|
-
* whether it stays top-level or moves into a group
|
|
152
|
+
* whether it stays top-level or moves into a group, at any nesting depth, since `target` stays the
|
|
154
153
|
* slide all the way down.
|
|
155
154
|
*
|
|
156
155
|
* Shapes and text boxes deliberately share the `text` bucket (both are `_type === text`), which is
|
|
@@ -169,7 +168,7 @@ function nextObjectNameIdx(target, type) {
|
|
|
169
168
|
}
|
|
170
169
|
/**
|
|
171
170
|
* The Selection Pane name an object takes: the caller's, validated and kept as they wrote it, or the
|
|
172
|
-
* next default for its kind
|
|
171
|
+
* next default for its kind: `Shape 1`, `Image 1`, `Group 1`, `Slide Zoom 1`, …
|
|
173
172
|
*
|
|
174
173
|
* The name is stored raw and escaped once, when `cNvPrOpen` writes it. It used to be escaped here,
|
|
175
174
|
* so any path that handed a stored name back in as a supplied one escaped it a second time: a layout
|
|
@@ -177,7 +176,7 @@ function nextObjectNameIdx(target, type) {
|
|
|
177
176
|
*
|
|
178
177
|
* Eleven definers wrote this out, and the index base they appended used to disagree: six counted
|
|
179
178
|
* from 0 (`Shape 0`, `Text 0`, `Image 0`, `Connector 0`, `Media 0`, `Table 0`), four from 1
|
|
180
|
-
* (`Group 1`, `Object 1`, `3D Model 1`, and the zoom tiles), and `addChart` neither
|
|
179
|
+
* (`Group 1`, `Object 1`, `3D Model 1`, and the zoom tiles), and `addChart` neither: it derived
|
|
181
180
|
* `Chart 0` by counting the chart objects already on the slide, which is the numbering this
|
|
182
181
|
* counter exists to replace ({@link nextObjectNameIdx}).
|
|
183
182
|
*
|
|
@@ -187,15 +186,15 @@ function nextObjectNameIdx(target, type) {
|
|
|
187
186
|
* name outside this counter is the slide-number placeholder, which the slide emitter writes as
|
|
188
187
|
* `Slide Number Placeholder 0`.
|
|
189
188
|
*
|
|
190
|
-
* The index is taken unconditionally
|
|
189
|
+
* The index is taken unconditionally, including when the caller supplied a name, so an object's
|
|
191
190
|
* index is its ordinal among its kind. See {@link nextObjectNameIdx}.
|
|
192
191
|
*
|
|
193
192
|
* @param target - slide (or master) the object is being added to
|
|
194
193
|
* @param type - the object's `_type`, which selects the counter bucket
|
|
195
194
|
* @param spec - `label` opens the default name, `kind` names the API in a validation warning, and
|
|
196
195
|
* `supplied` is the caller's own name when they gave one. `fallback` replaces the `label N`
|
|
197
|
-
* default for a kind that has a better one to offer
|
|
198
|
-
* placeholder it fills
|
|
196
|
+
* default for a kind that has a better one to offer (a placeholder is named after the
|
|
197
|
+
* placeholder it fills) and is used as given, since it is the library's own string rather than
|
|
199
198
|
* the caller's and has nothing to validate.
|
|
200
199
|
*/
|
|
201
200
|
function resolveObjectName(target, type, spec) {
|
|
@@ -203,8 +202,7 @@ function resolveObjectName(target, type, spec) {
|
|
|
203
202
|
if (spec.supplied) return validateObjectName(spec.supplied, spec.kind);
|
|
204
203
|
return spec.fallback ?? `${spec.label} ${idx + 1}`;
|
|
205
204
|
}
|
|
206
|
-
|
|
207
|
-
//#region src/families/shared.ts
|
|
205
|
+
// src/families/shared.ts
|
|
208
206
|
/** Which family supplies each slide method, as data, so a program can name a family it never linked. */
|
|
209
207
|
const SLIDE_METHOD_FAMILIES = Object.freeze({
|
|
210
208
|
addAnimation: "animations",
|
|
@@ -233,7 +231,7 @@ const PRESENTATION_METHOD_FAMILIES = Object.freeze({
|
|
|
233
231
|
tableToSlides: "table"
|
|
234
232
|
});
|
|
235
233
|
/**
|
|
236
|
-
* Which family supplies each child descriptor, as data
|
|
234
|
+
* Which family supplies each child descriptor, as data. It is the counterpart to
|
|
237
235
|
* {@link SLIDE_METHOD_FAMILIES}, and for the same reason: a descriptor key that reaches a
|
|
238
236
|
* presentation composed without its family has to be able to name the family it is missing.
|
|
239
237
|
*
|
|
@@ -300,18 +298,17 @@ function requirePresentationAuthor(authors, method) {
|
|
|
300
298
|
if (!author) familyMethodUnavailable(`pptx.${method}`, PRESENTATION_METHOD_FAMILIES[method]);
|
|
301
299
|
return author;
|
|
302
300
|
}
|
|
303
|
-
|
|
304
|
-
//#region src/gen/define/group.ts
|
|
301
|
+
// src/gen/define/group.ts
|
|
305
302
|
/**
|
|
306
303
|
* Dispatch a key-tagged child-object descriptor (`{ text }`, `{ image }`, `{ shape }`, …) to the
|
|
307
304
|
* family that recognizes it. Shared by `createSlideMaster` (slide master `objects`) and
|
|
308
305
|
* `addGroupDefinition` (group children) so the descriptor mapping lives in one place.
|
|
309
306
|
*
|
|
310
307
|
* The mapping is handed in rather than spelled here. It used to be an `if` chain naming four
|
|
311
|
-
* `add*Definition` functions, which put the chart definer
|
|
308
|
+
* `add*Definition` functions, which put the chart definer (and every plot module under it) in the
|
|
312
309
|
* graph of any program that can define a slide master, which is all of them.
|
|
313
310
|
*
|
|
314
|
-
* `placeholder` is intentionally not handled here
|
|
311
|
+
* `placeholder` is intentionally not handled here: it is master-specific and needs the object's
|
|
315
312
|
* index for `_placeholderIdx`, so `createSlideMaster` handles that case itself.
|
|
316
313
|
* @param target - slide (or master) the object is appended to
|
|
317
314
|
* @param object - the child descriptor
|
|
@@ -331,7 +328,7 @@ function addChildDefinition(target, object, children) {
|
|
|
331
328
|
* Warn about a child descriptor {@link addChildDefinition} did not author, from `call`.
|
|
332
329
|
*
|
|
333
330
|
* Two conditions arrive here and they have different fixes, so they get different codes. A key
|
|
334
|
-
* {@link CHILD_DESCRIPTOR_FAMILIES} claims is valid and typed and was simply left uncomposed
|
|
331
|
+
* {@link CHILD_DESCRIPTOR_FAMILIES} claims is valid and typed and was simply left uncomposed:
|
|
335
332
|
* the family that would have drawn it is not in this presentation's list, so the message names it
|
|
336
333
|
* the way `familyMethodUnavailable` names the family behind a missing method. Any other key is a
|
|
337
334
|
* typo, which is all this walk used to be able to say, because before the split a descriptor that
|
|
@@ -352,7 +349,7 @@ function warnUnauthoredChild(object, call) {
|
|
|
352
349
|
* group itself to the slide. Nested `group` children recurse, so a group can contain other groups.
|
|
353
350
|
*
|
|
354
351
|
* An identity child coordinate space is kept at every depth (emitted in `gen/slide/object.ts` as
|
|
355
|
-
* `chOff/chExt == off/ext`), so children
|
|
352
|
+
* `chOff/chExt == off/ext`), so children, including descendants of nested groups, keep their
|
|
356
353
|
* slide-absolute coordinates and grouping is visually a no-op while making the objects one
|
|
357
354
|
* selectable PowerPoint group. Charts, media, tables, and placeholders are not supported as group
|
|
358
355
|
* children yet; each is skipped with a warning. When `opts.x/y/w/h` are omitted the group's bounds
|
|
@@ -390,7 +387,7 @@ function buildGroupObject(target, children, opts, childAuthors) {
|
|
|
390
387
|
* Wrap already-built child render-objects in a group (`<p:grpSp>`) render-object, without appending
|
|
391
388
|
* the group anywhere. Shared by `buildGroupObject` (children built from descriptors) and
|
|
392
389
|
* `groupObjectsDefinition` (children lifted off the slide) so both entry points name and frame a
|
|
393
|
-
* group identically
|
|
390
|
+
* group identically, including the all-or-nothing frame, which is left to `gen/slide/object.ts` to resolve:
|
|
394
391
|
* passing `x/y/w/h` through unset is what makes the bounds auto-compute to the children's bounding
|
|
395
392
|
* box, so neither caller needs bounds math of its own.
|
|
396
393
|
*
|
|
@@ -437,7 +434,7 @@ function addGroupDefinition(target, children, opts, childAuthors) {
|
|
|
437
434
|
}
|
|
438
435
|
/**
|
|
439
436
|
* Object kinds `groupObjects()` accepts. Text (which shapes and text boxes both are), images,
|
|
440
|
-
* connectors, and groups
|
|
437
|
+
* connectors, and groups; the last so consumers can build nested logical groups out of groups they
|
|
441
438
|
* already made. Charts, media, tables, and placeholders are excluded for the same reason
|
|
442
439
|
* `addGroup()` excludes them (rels/id/transform work pending); a placeholder is excluded on top of
|
|
443
440
|
* that because grouping it would sever the layout inheritance that makes it a placeholder.
|
|
@@ -450,8 +447,8 @@ const GROUPABLE_TYPES = [
|
|
|
450
447
|
];
|
|
451
448
|
/**
|
|
452
449
|
* Whether `groupObjects()` would accept this object, given only what it is. The remaining reasons a
|
|
453
|
-
* call can still fail are about the *selection* rather than the object
|
|
454
|
-
* or ambiguous name
|
|
450
|
+
* call can still fail are about the *selection* rather than the object (an unresolved, duplicated
|
|
451
|
+
* or ambiguous name), so a consumer cannot decide those from one object either way.
|
|
455
452
|
*
|
|
456
453
|
* Exported because `Slide.objects` reports it as `canGroup`, and a consumer that had to re-state the
|
|
457
454
|
* rule would be pinning a copy of the list above: it would keep refusing the day grouping learns a
|
|
@@ -478,14 +475,14 @@ function findNameInGroups(objects, name) {
|
|
|
478
475
|
* renderers: the objects already exist, so replaying their descriptors just to group them would mean
|
|
479
476
|
* every renderer exposing its internals.
|
|
480
477
|
*
|
|
481
|
-
* Grouping is visually a no-op
|
|
478
|
+
* Grouping is visually a no-op: children keep their slide-absolute geometry, their ids, their rels,
|
|
482
479
|
* and their relative z-order, exactly as with `addGroup()`. Two ordering rules make that true:
|
|
483
480
|
* children are ordered by their existing slide z-order (**not** by the order they are named, which
|
|
484
481
|
* would silently restack the slide), and the group itself takes the topmost member's former slot, so
|
|
485
482
|
* it lands where the selection's top edge already was.
|
|
486
483
|
*
|
|
487
484
|
* Every failure here throws rather than warns. An unmatched name is not a degenerate deck the author
|
|
488
|
-
* might still want
|
|
485
|
+
* might still want. It means the intended object is silently still loose on the slide, which is the
|
|
489
486
|
* footgun the group was meant to remove.
|
|
490
487
|
* @param target - slide holding the objects
|
|
491
488
|
* @param objectNames - `objectName`s of the top-level objects to group
|
|
@@ -505,12 +502,12 @@ function groupObjectsDefinition(target, objectNames, opts) {
|
|
|
505
502
|
const [obj, ambiguous] = matches;
|
|
506
503
|
if (!obj) {
|
|
507
504
|
const hint = findNameInGroups(target._slideObjects, name) ? "it is already inside a group (an object can only belong to one group)" : "no top-level object on this slide has that objectName";
|
|
508
|
-
throw new InvalidOptionError("group/unresolved-object-name", `groupObjects(): cannot group "${name}"
|
|
505
|
+
throw new InvalidOptionError("group/unresolved-object-name", `groupObjects(): cannot group "${name}": ${hint}.`);
|
|
509
506
|
}
|
|
510
|
-
if (ambiguous) throw new InvalidOptionError("group/ambiguous-object-name", `groupObjects(): objectName "${name}" is ambiguous
|
|
507
|
+
if (ambiguous) throw new InvalidOptionError("group/ambiguous-object-name", `groupObjects(): objectName "${name}" is ambiguous: ${matches.length} objects on this slide share it. Give them unique objectNames.`);
|
|
511
508
|
if (!isGroupableObject(obj)) {
|
|
512
509
|
const kind = obj.options?.placeholder ? "placeholder" : obj._type;
|
|
513
|
-
throw new UnsupportedFeatureError("group/kind-not-groupable", `groupObjects(): cannot group "${name}"
|
|
510
|
+
throw new UnsupportedFeatureError("group/kind-not-groupable", `groupObjects(): cannot group "${name}": grouping a ${String(kind)} is not supported yet.`);
|
|
514
511
|
}
|
|
515
512
|
members.push(obj);
|
|
516
513
|
});
|
|
@@ -522,8 +519,7 @@ function groupObjectsDefinition(target, objectNames, opts) {
|
|
|
522
519
|
regrouped.splice(insertAt, 0, makeGroupObject(target, children, opts));
|
|
523
520
|
target._slideObjects.splice(0, target._slideObjects.length, ...regrouped);
|
|
524
521
|
}
|
|
525
|
-
|
|
526
|
-
//#region src/gen/slide/shape-ids.ts
|
|
522
|
+
// src/gen/slide/shape-ids.ts
|
|
527
523
|
/**
|
|
528
524
|
* The four `SlideObjectType` members that live in `_slideObjects` without drawing anything on the
|
|
529
525
|
* slide: speaker notes belong to the notes part, a table cell is rendered by its owning table, a
|
|
@@ -573,8 +569,8 @@ function shapeIdCount(obj) {
|
|
|
573
569
|
* map names a shape that exists.
|
|
574
570
|
*
|
|
575
571
|
* This **mirrors** the allocation in `slideObjectToXml`, which hands out ids as it walks the tree.
|
|
576
|
-
* A reference that must name an id *before* the walk reaches it
|
|
577
|
-
* animation's `<p:spTgt spid>`
|
|
572
|
+
* A reference that must name an id *before* the walk reaches it (a connector's `<a:stCxn>`, an
|
|
573
|
+
* animation's `<p:spTgt spid>`) cannot wait for that, so it resolves through this map instead.
|
|
578
574
|
* The two must stay in step: `test/regression/shape/group-shapes.test.ts` parses the emitted `cNvPr` ids
|
|
579
575
|
* back out and asserts each reference points at the shape it names, so drift fails there.
|
|
580
576
|
* @param slideObjects - the slide's top-level objects
|
|
@@ -623,8 +619,7 @@ function resolveObjectNameToId(shapeIds, objectName) {
|
|
|
623
619
|
for (const [obj, id] of shapeIds) if (obj.options?.objectName === objectName) return id;
|
|
624
620
|
return null;
|
|
625
621
|
}
|
|
626
|
-
|
|
627
|
-
//#region src/gen/drawingml/text-body.ts
|
|
622
|
+
// src/gen/drawingml/text-body.ts
|
|
628
623
|
/**
|
|
629
624
|
* pptx-ts: DrawingML text body
|
|
630
625
|
*
|
|
@@ -640,7 +635,7 @@ const PLACEHOLDER_TYPE_MAP = PlaceholderType;
|
|
|
640
635
|
*/
|
|
641
636
|
function genXmlBodyProperties(slideObject) {
|
|
642
637
|
if (slideObject._type === "tablecell") return voidEl("a:bodyPr");
|
|
643
|
-
if (
|
|
638
|
+
if (slideObject._type !== "text" && slideObject._type !== "placeholder") return el("a:bodyPr", {
|
|
644
639
|
wrap: "square",
|
|
645
640
|
rtlCol: "0"
|
|
646
641
|
});
|
|
@@ -679,12 +674,12 @@ function genXmlBodyProperties(slideObject) {
|
|
|
679
674
|
* nothing usable.
|
|
680
675
|
*
|
|
681
676
|
* `null` means "no answer here", not "omit the attribute": each call site then applies its own
|
|
682
|
-
* default
|
|
677
|
+
* default. The text definer's is `ctr`, while a table cell and the slide-number placeholder
|
|
683
678
|
* leave the attribute off and inherit.
|
|
684
679
|
*
|
|
685
680
|
* `ST_TextAnchoringType` is an enumeration, so a string outside it makes PowerPoint report the
|
|
686
|
-
* package as needing repair. Typed callers are unaffected
|
|
687
|
-
* `'top' | 'middle' | 'bottom'`
|
|
681
|
+
* package as needing repair. Typed callers are unaffected (`VAlign` is
|
|
682
|
+
* `'top' | 'middle' | 'bottom'`), and a JavaScript caller passing something else now gets a
|
|
688
683
|
* diagnostic instead of an attribute the schema rejects.
|
|
689
684
|
* @param valign - the caller's `valign`, in any of the spellings above
|
|
690
685
|
*/
|
|
@@ -704,6 +699,7 @@ function objectHasMath(slideObj) {
|
|
|
704
699
|
/**
|
|
705
700
|
* Generate the XML for text and its options (bold, bullet, etc) including text runs (word-level formatting)
|
|
706
701
|
* @param {SlideObject|TableCellInternal} slideObj - slideObj or tableCell
|
|
702
|
+
* @param slideColor - the colour a run marked `_slideColor` is written in: the slide's, else black
|
|
707
703
|
* @note PPT text lines [lines followed by line-breaks] are created using <p>-aragraph's
|
|
708
704
|
* @note Bullets are a paragragh-level formatting device
|
|
709
705
|
* @template
|
|
@@ -723,18 +719,18 @@ function objectHasMath(slideObj) {
|
|
|
723
719
|
* </p:txBody>
|
|
724
720
|
* @returns XML containing the param object's text and formatting
|
|
725
721
|
*/
|
|
726
|
-
function genXmlTextBody(slideObj) {
|
|
722
|
+
function genXmlTextBody(slideObj, slideColor = DEF_FONT_COLOR) {
|
|
727
723
|
const opts = slideObj.options || {};
|
|
728
724
|
let tmpTextObjects = [];
|
|
729
725
|
const arrTextObjects = [];
|
|
730
726
|
let strSlideXml = "";
|
|
731
727
|
strSlideXml += genXmlBodyProperties(slideObj);
|
|
732
728
|
if (opts.h === 0 && opts.line && opts.align) strSlideXml += el("a:lstStyle", null, raw(voidEl("a:lvl1pPr", { algn: "l" })));
|
|
733
|
-
else if (slideObj._type === "placeholder") strSlideXml += el("a:lstStyle", null, raw(genXmlParagraphProperties(slideObj, true)));
|
|
729
|
+
else if (slideObj._type === "placeholder" && !slideObj._seeded) strSlideXml += el("a:lstStyle", null, raw(genXmlParagraphProperties(slideObj, true)));
|
|
734
730
|
else strSlideXml += voidEl("a:lstStyle");
|
|
735
731
|
if (typeof slideObj.text === "string" || typeof slideObj.text === "number") tmpTextObjects.push({
|
|
736
732
|
text: slideObj.text.toString(),
|
|
737
|
-
options: opts
|
|
733
|
+
options: opts
|
|
738
734
|
});
|
|
739
735
|
else if (Array.isArray(slideObj.text)) tmpTextObjects = slideObj.text.map((item) => {
|
|
740
736
|
const projected = {};
|
|
@@ -746,8 +742,8 @@ function genXmlTextBody(slideObj) {
|
|
|
746
742
|
});
|
|
747
743
|
tmpTextObjects.forEach((itext, idx) => {
|
|
748
744
|
if (!itext.text) itext.text = "";
|
|
749
|
-
itext.options = itext.options || opts
|
|
750
|
-
if (idx === 0 &&
|
|
745
|
+
itext.options = itext.options || opts;
|
|
746
|
+
if (idx === 0 && !itext.options.bullet && opts.bullet) itext.options.bullet = opts.bullet;
|
|
751
747
|
if (typeof itext.text === "string" || typeof itext.text === "number") itext.text = itext.text.toString().replace(/\r*\n/g, "\r\n");
|
|
752
748
|
if (itext.text.includes("\r\n") && itext.text.match(/\n$/g) === null) {
|
|
753
749
|
const lines = itext.text.split("\r\n");
|
|
@@ -762,33 +758,36 @@ function genXmlTextBody(slideObj) {
|
|
|
762
758
|
});
|
|
763
759
|
} else arrTextObjects.push({
|
|
764
760
|
...itext,
|
|
765
|
-
options: itext.options
|
|
761
|
+
options: itext.options
|
|
766
762
|
});
|
|
767
763
|
});
|
|
768
764
|
const arrLines = groupRunsIntoLines(arrTextObjects, opts);
|
|
769
|
-
strSlideXml += renderTextParagraphsXml(arrLines, slideObj, opts);
|
|
765
|
+
strSlideXml += renderTextParagraphsXml(arrLines, slideObj, opts, slideColor);
|
|
770
766
|
if (!strSlideXml.includes("<a:p>")) strSlideXml += el("a:p", null, raw(voidEl("a:endParaRPr")));
|
|
771
767
|
return el(slideObj._type === "tablecell" ? "a:txBody" : "p:txBody", null, raw(strSlideXml));
|
|
772
768
|
}
|
|
773
769
|
/**
|
|
774
770
|
* Generate an XML Placeholder
|
|
775
771
|
* @param {SlideObject} placeholderObj
|
|
772
|
+
* @param binding - the `type` and `idx` the slide object states itself, each winning over
|
|
773
|
+
* `placeholderObj`'s; with one, a `p:ph` is written even when `placeholderObj` is `null`
|
|
774
|
+
* @param definition - `placeholderObj` is the layout or master placeholder being written, not the
|
|
775
|
+
* one a slide object fills
|
|
776
776
|
* @returns XML
|
|
777
777
|
*/
|
|
778
|
-
function genXmlPlaceholder(placeholderObj) {
|
|
779
|
-
if (!placeholderObj) return "";
|
|
780
|
-
const placeholderIdx =
|
|
781
|
-
const placeholderTyp = placeholderObj
|
|
782
|
-
const placeholderType = PLACEHOLDER_TYPE_MAP[placeholderTyp] ? PLACEHOLDER_TYPE_MAP[placeholderTyp].toString() : Object.values(PlaceholderType).includes(placeholderTyp) ? placeholderTyp : "";
|
|
783
|
-
const
|
|
778
|
+
function genXmlPlaceholder(placeholderObj, binding, definition = false) {
|
|
779
|
+
if (!placeholderObj && !binding) return "";
|
|
780
|
+
const placeholderIdx = binding?.idx ?? (placeholderObj?.options?._placeholderIdx || "");
|
|
781
|
+
const placeholderTyp = placeholderObj?.options?._placeholderType ? placeholderObj.options._placeholderType : "";
|
|
782
|
+
const placeholderType = binding?.type ?? (PLACEHOLDER_TYPE_MAP[placeholderTyp] ? PLACEHOLDER_TYPE_MAP[placeholderTyp].toString() : Object.values(PlaceholderType).includes(placeholderTyp) || placeholderObj?._type === "placeholder" && PLACEHOLDER_TYPES.includes(placeholderTyp) ? placeholderTyp : "");
|
|
783
|
+
const hasCustomPrompt = definition && placeholderObj?._type === "placeholder" && (placeholderObj.text ?? []).some((run) => typeof run.text === "string" && run.text.length > 0);
|
|
784
784
|
return `<p:ph
|
|
785
|
-
${placeholderIdx ? " idx=\"" + placeholderIdx.toString() + "\"" : ""}
|
|
785
|
+
${placeholderIdx !== "" ? " idx=\"" + placeholderIdx.toString() + "\"" : ""}
|
|
786
786
|
${placeholderType ? ` type="${placeholderType}"` : ""}
|
|
787
|
-
${
|
|
787
|
+
${hasCustomPrompt ? " hasCustomPrompt=\"1\"" : ""}
|
|
788
788
|
/>`;
|
|
789
789
|
}
|
|
790
|
-
|
|
791
|
-
//#region src/gen/define/frame.ts
|
|
790
|
+
// src/gen/define/frame.ts
|
|
792
791
|
/**
|
|
793
792
|
* pptx-ts: an authored object's frame
|
|
794
793
|
*
|
|
@@ -847,19 +846,43 @@ function resolveAuthoredFrame(given, defaults, api, zeroExtentAllowed = false) {
|
|
|
847
846
|
}
|
|
848
847
|
return frame;
|
|
849
848
|
}
|
|
850
|
-
|
|
851
|
-
|
|
849
|
+
// src/gen/define/layout-placeholder.ts
|
|
850
|
+
/** The layout placeholder name a `placeholder` option states: the string, or a binding's `name`. */
|
|
851
|
+
function layoutPlaceholderName(option) {
|
|
852
|
+
return typeof option === "object" && option !== null ? option.name : option;
|
|
853
|
+
}
|
|
852
854
|
/**
|
|
853
|
-
* The
|
|
854
|
-
* `
|
|
855
|
+
* The binding a `placeholder` option states its `p:ph` with, or `undefined` when it states neither
|
|
856
|
+
* `type` nor `idx` and so binds by name alone, exactly as the string does.
|
|
857
|
+
*/
|
|
858
|
+
function statedPlaceholderBinding(option) {
|
|
859
|
+
if (typeof option !== "object" || option === null) return void 0;
|
|
860
|
+
return option.type !== void 0 || option.idx !== void 0 ? option : void 0;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Throw on a binding whose `idx` or `type` has no `p:ph` spelling, so a bad value fails where it
|
|
864
|
+
* was written rather than dropping out of the slide XML.
|
|
865
|
+
* @param option - the slide object's `placeholder` option
|
|
866
|
+
* @param label - the option's owner, as an error message names it (`addText`, `addImage`)
|
|
867
|
+
*/
|
|
868
|
+
function checkPlaceholderBinding(option, label) {
|
|
869
|
+
if (typeof option !== "object" || option === null) return;
|
|
870
|
+
const { idx, type } = option;
|
|
871
|
+
if (idx !== void 0 && !(Number.isInteger(idx) && idx >= 0 && idx <= 4294967295)) throw new InvalidOptionError("placeholder/invalid-idx", `${label} placeholder.idx must be an integer from 0 to 4294967295 (got ${String(idx)}).`);
|
|
872
|
+
if (type !== void 0 && !PLACEHOLDER_TYPES.includes(type)) throw new InvalidOptionError("placeholder/invalid-type", `${label} placeholder.type must be one of ${PLACEHOLDER_TYPES.join(", ")} (got ${String(type)}).`);
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* The layout placeholder a `placeholder` option names: the first `placeholder` object on the
|
|
876
|
+
* layout whose `placeholder` option is that name.
|
|
855
877
|
*
|
|
856
878
|
* Only placeholder objects qualify. A layout text box can carry a `placeholder` option too, but it is
|
|
857
879
|
* not a placeholder a slide can bind a `<p:ph>` to or inherit from.
|
|
858
880
|
* @param layout - the slide's layout, if it has one
|
|
859
|
-
* @param
|
|
881
|
+
* @param option - the slide object's `placeholder` option, if any
|
|
860
882
|
* @returns the layout placeholder, or `null` when there is none
|
|
861
883
|
*/
|
|
862
|
-
function findLayoutPlaceholder(layout,
|
|
884
|
+
function findLayoutPlaceholder(layout, option) {
|
|
885
|
+
const name = layoutPlaceholderName(option);
|
|
863
886
|
if (!layout?._slideObjects || !name) return null;
|
|
864
887
|
return layout._slideObjects.find((obj) => obj._type === "placeholder" && obj.options?.placeholder === name) ?? null;
|
|
865
888
|
}
|
|
@@ -871,11 +894,11 @@ function findLayoutPlaceholder(layout, name) {
|
|
|
871
894
|
* treated a `null` axis as unstated and the table did not, so `x: null` put an image at the
|
|
872
895
|
* placeholder's left edge and a table at the default half inch.
|
|
873
896
|
* @param layout - the slide's layout, if it has one
|
|
874
|
-
* @param
|
|
897
|
+
* @param option - the slide object's `placeholder` option, if any
|
|
875
898
|
* @returns the placeholder's axes, each absent when it states none or there is no such placeholder
|
|
876
899
|
*/
|
|
877
|
-
function placeholderFrame(layout,
|
|
878
|
-
const options = findLayoutPlaceholder(layout,
|
|
900
|
+
function placeholderFrame(layout, option) {
|
|
901
|
+
const options = findLayoutPlaceholder(layout, option)?.options;
|
|
879
902
|
return options ? {
|
|
880
903
|
x: options.x,
|
|
881
904
|
y: options.y,
|
|
@@ -883,8 +906,7 @@ function placeholderFrame(layout, name) {
|
|
|
883
906
|
h: options.h
|
|
884
907
|
} : {};
|
|
885
908
|
}
|
|
886
|
-
|
|
887
|
-
//#region src/gen/define/image.ts
|
|
909
|
+
// src/gen/define/image.ts
|
|
888
910
|
/** DPI PowerPoint assumes when sizing an inserted raster image (natural pixels / 96 == inches) */
|
|
889
911
|
const IMAGE_NATURAL_DPI = 96;
|
|
890
912
|
/**
|
|
@@ -931,7 +953,7 @@ function registerImageFillMedia(target, fill) {
|
|
|
931
953
|
* Normalize an `addImage()` call into a slide image object and register its media relationships.
|
|
932
954
|
*
|
|
933
955
|
* Resolves the image source (path or base64 `data:`), allocates the drawing relationship id(s)
|
|
934
|
-
*
|
|
956
|
+
* (SVG needs a second rId for its PNG rasterization fallback), appends the bytes to
|
|
935
957
|
* `target._relsMedia` (deduping identical sources), and inherits any omitted x/y/w/h from a
|
|
936
958
|
* matching layout picture placeholder. The resulting `SlideObject` is pushed onto the slide;
|
|
937
959
|
* `gen/slide/objects/image.ts` later emits the `<p:pic>`.
|
|
@@ -940,6 +962,7 @@ function registerImageFillMedia(target, fill) {
|
|
|
940
962
|
*/
|
|
941
963
|
function addImageDefinition(target, opt) {
|
|
942
964
|
const newObject = { _type: "image" };
|
|
965
|
+
checkPlaceholderBinding(opt.placeholder, "addImage");
|
|
943
966
|
const placeholder = placeholderFrame(target._slideLayout, opt.placeholder);
|
|
944
967
|
const givenX = opt.x ?? placeholder.x;
|
|
945
968
|
const givenY = opt.y ?? placeholder.y;
|
|
@@ -963,7 +986,6 @@ function addImageDefinition(target, opt) {
|
|
|
963
986
|
supplied: opt.objectName
|
|
964
987
|
});
|
|
965
988
|
const strImgExtn = source.extn;
|
|
966
|
-
newObject._type = "image";
|
|
967
989
|
newObject.image = strImagePath || preencodedPath("png");
|
|
968
990
|
let defWidth = givenW;
|
|
969
991
|
let defHeight = givenH;
|
|
@@ -1046,8 +1068,7 @@ function addImageDefinition(target, opt) {
|
|
|
1046
1068
|
}
|
|
1047
1069
|
target._slideObjects.push(newObject);
|
|
1048
1070
|
}
|
|
1049
|
-
|
|
1050
|
-
//#region src/gen/define/text.ts
|
|
1071
|
+
// src/gen/define/text.ts
|
|
1051
1072
|
/**
|
|
1052
1073
|
* pptx-ts: Text Definition
|
|
1053
1074
|
*
|
|
@@ -1064,6 +1085,7 @@ function addImageDefinition(target, opt) {
|
|
|
1064
1085
|
* @param {boolean} isPlaceholder whether this a placeholder object
|
|
1065
1086
|
*/
|
|
1066
1087
|
function addTextDefinition(target, text, opts, isPlaceholder) {
|
|
1088
|
+
checkPlaceholderBinding(opts.placeholder, "addText");
|
|
1067
1089
|
const owned = /* @__PURE__ */ new Map();
|
|
1068
1090
|
/**
|
|
1069
1091
|
* The keys the CALLER wrote on each owned copy, recorded before any default reaches it.
|
|
@@ -1100,20 +1122,23 @@ function addTextDefinition(target, text, opts, isPlaceholder) {
|
|
|
1100
1122
|
if (!(Boolean(itemOpts.placeholder ?? objectOptions.placeholder) || isPlaceholder)) {
|
|
1101
1123
|
rejectEmptyColor(itemOpts.color, "color");
|
|
1102
1124
|
rejectEmptyColor(objectOptions.color, "color");
|
|
1103
|
-
|
|
1125
|
+
const linked = Boolean(itemOpts.hyperlink || objectOptions.hyperlink);
|
|
1126
|
+
const shapeColor = linked && !authoredKeys.get(objectOptions)?.has("color") ? void 0 : objectOptions.color;
|
|
1127
|
+
const color = itemOpts.color || shapeColor || void 0;
|
|
1128
|
+
setOrClear(itemOpts, "color", color);
|
|
1129
|
+
setOrClear(itemOpts, "_slideColor", color === void 0 && !linked ? true : void 0);
|
|
1104
1130
|
}
|
|
1105
|
-
if (
|
|
1106
|
-
if (itemOpts.placeholder
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
}
|
|
1131
|
+
if (isPlaceholder) itemOpts.bullet = itemOpts.bullet ?? "inherit";
|
|
1132
|
+
else if (itemOpts.placeholder) itemOpts.bullet = itemOpts.bullet || false;
|
|
1133
|
+
const placeHold = findLayoutPlaceholder(target._slideLayout, itemOpts.placeholder);
|
|
1134
|
+
if (placeHold?.options) {
|
|
1135
|
+
const stated = authoredKeys.get(itemOpts) ?? /* @__PURE__ */ new Set();
|
|
1136
|
+
const inherited = {};
|
|
1137
|
+
for (const [key, value] of Object.entries(placeholderOptionsForSlide(placeHold.options))) if (value !== void 0 && !stated.has(key)) inherited[key] = value;
|
|
1138
|
+
itemOpts = {
|
|
1139
|
+
...itemOpts,
|
|
1140
|
+
...inherited
|
|
1141
|
+
};
|
|
1117
1142
|
}
|
|
1118
1143
|
itemOpts.line = itemOpts.line || {};
|
|
1119
1144
|
if (itemOpts.shape === "line" && typeof itemOpts.line === "object") itemOpts.line = withLineDefaults(itemOpts.line, "line.color");
|
|
@@ -1137,7 +1162,6 @@ function addTextDefinition(target, text, opts, isPlaceholder) {
|
|
|
1137
1162
|
if (typeof itemOpts.columnSpacing !== "number" || !Number.isFinite(itemOpts.columnSpacing) || itemOpts.columnSpacing < 0) warn("text/invalid-column-spacing", "text `columnSpacing` must be a number >= 0 (ignoring value)");
|
|
1138
1163
|
else itemOpts._bodyProp.spcCol = ptsToEmuLenient(itemOpts.columnSpacing);
|
|
1139
1164
|
}
|
|
1140
|
-
if (typeof itemOpts.underline === "boolean" && itemOpts.underline === true) itemOpts.underline = { style: "sng" };
|
|
1141
1165
|
}
|
|
1142
1166
|
{
|
|
1143
1167
|
const align = (itemOpts.align || "").toLowerCase();
|
|
@@ -1153,17 +1177,19 @@ function addTextDefinition(target, text, opts, isPlaceholder) {
|
|
|
1153
1177
|
}
|
|
1154
1178
|
newObject.options = cleanOpts(objectOptions);
|
|
1155
1179
|
if (newObject.shape !== "line") Object.assign(newObject.options, resolveAuthoredFrame(newObject.options, { h: .3 }, "addText"));
|
|
1156
|
-
const placeholderName = isPlaceholder ? String(newObject.options.placeholder || newObject.options._placeholderType || `Placeholder ${newObject.options._placeholderIdx ?? target._slideObjects.length}`) : void 0;
|
|
1180
|
+
const placeholderName = isPlaceholder ? String(layoutPlaceholderName(newObject.options.placeholder) || newObject.options._placeholderType || `Placeholder ${newObject.options._placeholderIdx ?? target._slideObjects.length}`) : void 0;
|
|
1157
1181
|
newObject.options.objectName = resolveObjectName(target, newObject._type, {
|
|
1158
1182
|
label: "Text",
|
|
1159
1183
|
kind: "text",
|
|
1160
1184
|
supplied: newObject.options.objectName,
|
|
1161
1185
|
...placeholderName === void 0 ? {} : { fallback: placeholderName }
|
|
1162
1186
|
});
|
|
1163
|
-
|
|
1164
|
-
|
|
1187
|
+
const placeholder = newObject.options.placeholder;
|
|
1188
|
+
const fallbackType = statedPlaceholderBinding(placeholder) ? void 0 : layoutPlaceholderName(placeholder);
|
|
1189
|
+
if (!isPlaceholder && fallbackType && !newObject.options._placeholderType) newObject.options._placeholderType = fallbackType;
|
|
1190
|
+
textObjects.forEach((item) => item.options = cleanOpts(item.options));
|
|
1165
1191
|
createHyperlinkRels(target, newObject);
|
|
1166
|
-
createBulletImageRels(target, newObject.options, textObjects);
|
|
1192
|
+
createBulletImageRels(target, [newObject.options, ...textObjects.map((item) => item.options)]);
|
|
1167
1193
|
if (typeof newObject.options.fill === "object" && resolveFillKind(newObject.options.fill) === "image") registerImageFillMedia(target, newObject.options.fill);
|
|
1168
1194
|
target._slideObjects.push(newObject);
|
|
1169
1195
|
}
|
|
@@ -1198,22 +1224,33 @@ function placeholderOptionsForSlide(options) {
|
|
|
1198
1224
|
return copy;
|
|
1199
1225
|
}
|
|
1200
1226
|
/**
|
|
1201
|
-
* Register slide media relationships for any picture bullets (`bullet.image`)
|
|
1202
|
-
* Picture bullets render as `<a:buBlip><a:blip r:embed="rId.."/></a:buBlip>`, so the bullet
|
|
1203
|
-
* needs the same media-rel + package-part plumbing as `addImage()`. The assigned `rId` is
|
|
1204
|
-
* the bullet
|
|
1227
|
+
* Register slide media relationships for any picture bullets (`bullet.image`) the given option bags
|
|
1228
|
+
* use. Picture bullets render as `<a:buBlip><a:blip r:embed="rId.."/></a:buBlip>`, so the bullet
|
|
1229
|
+
* image needs the same media-rel + package-part plumbing as `addImage()`. The assigned `rId` is
|
|
1230
|
+
* stored on the bullet (`_rId`) so XML generation can reference it.
|
|
1231
|
+
*
|
|
1232
|
+
* The bullet each bag holds is replaced by a copy before anything is stamped on it. The bags are
|
|
1233
|
+
* the definer's own, but the bullet inside one is the caller's object, and an id stamped there
|
|
1234
|
+
* travelled with it: reused in another deck, it was written as an `r:embed` that deck never
|
|
1235
|
+
* declared (#83). One copy per bullet object, so a bullet shared between the shape and its runs
|
|
1236
|
+
* stays one object and registers once.
|
|
1205
1237
|
* @param {PresSlideInternal} target - slide receiving the rels
|
|
1206
|
-
* @param
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1238
|
+
* @param bags - the shape-level, table-level, per-paragraph or per-cell options a bullet may live on
|
|
1239
|
+
*/
|
|
1240
|
+
function createBulletImageRels(target, bags) {
|
|
1241
|
+
const copies = /* @__PURE__ */ new Map();
|
|
1242
|
+
for (const opts of bags) {
|
|
1243
|
+
if (!opts || typeof opts.bullet !== "object" || !opts.bullet) continue;
|
|
1244
|
+
const source = opts.bullet;
|
|
1245
|
+
if (!source.image) continue;
|
|
1246
|
+
let copy = copies.get(source);
|
|
1247
|
+
if (!copy) {
|
|
1248
|
+
copy = { ...source };
|
|
1249
|
+
copies.set(source, copy);
|
|
1250
|
+
}
|
|
1251
|
+
opts.bullet = copy;
|
|
1252
|
+
}
|
|
1253
|
+
copies.forEach((bullet) => {
|
|
1217
1254
|
const img = bullet.image;
|
|
1218
1255
|
if (!img || !img.path && !img.data) return;
|
|
1219
1256
|
const source = resolveImageSource(img);
|
|
@@ -1248,8 +1285,7 @@ function createBulletImageRels(target, objectOptions, textObjects) {
|
|
|
1248
1285
|
}
|
|
1249
1286
|
});
|
|
1250
1287
|
}
|
|
1251
|
-
|
|
1252
|
-
//#region src/gen/define/object-options.ts
|
|
1288
|
+
// src/gen/define/object-options.ts
|
|
1253
1289
|
/**
|
|
1254
1290
|
* The options an object's slide record carries: its frame, its Selection Pane name, and its alt
|
|
1255
1291
|
* text and lock flags when the caller stated them.
|
|
@@ -1286,8 +1322,7 @@ function framedObjectOptions(target, type, opt, spec) {
|
|
|
1286
1322
|
function requirePayloadSource(opt, code, api) {
|
|
1287
1323
|
if (!opt.path && !opt.data) throw new InvalidOptionError(code, `${api}(): either \`data\` or \`path\` are required!`);
|
|
1288
1324
|
}
|
|
1289
|
-
|
|
1290
|
-
//#region src/gen/define/media.ts
|
|
1325
|
+
// src/gen/define/media.ts
|
|
1291
1326
|
/**
|
|
1292
1327
|
* One media item costs three consecutive slide rels, allocated together by {@link addMedia}:
|
|
1293
1328
|
* the ECMA `audio`/`video` rel (the id kept on the object as `mediaRid`), the MS-2007 `media`
|
|
@@ -1304,7 +1339,7 @@ const msMediaRid = (mediaRid) => mediaRid + 1;
|
|
|
1304
1339
|
const previewRid = (mediaRid) => mediaRid + 2;
|
|
1305
1340
|
/**
|
|
1306
1341
|
* Check that a media item's three rels really did come out consecutive. The ids come from
|
|
1307
|
-
* three separate `getNewRelId` calls, so nothing but call order makes them so
|
|
1342
|
+
* three separate `getNewRelId` calls, so nothing but call order makes them so, and every
|
|
1308
1343
|
* reader of the triple assumes it.
|
|
1309
1344
|
*/
|
|
1310
1345
|
function assertConsecutiveMediaRids(base, second, third) {
|
|
@@ -1326,6 +1361,7 @@ function addMediaDefinition(target, opt) {
|
|
|
1326
1361
|
if (strData && !hasBase64Header(strData)) throw new InvalidOptionError("media/missing-base64-header", "addMedia(): `data` value lacks a base64 header! Ex: 'video/mpeg;base64,NMP[...]')");
|
|
1327
1362
|
else if (strCover && !hasBase64Header(strCover)) throw new InvalidOptionError("media/cover-missing-base64-header", "addMedia(): `cover` value lacks a base64 header! Ex: 'data:image/png;base64,iV[...]')");
|
|
1328
1363
|
if (strType === "online" && !strLink) throw new InvalidOptionError("media/online-missing-link", "addMedia(): online videos require `link` value");
|
|
1364
|
+
if (strType !== "online" && strLink) warn("media/option-not-supported", `addMedia(): \`link\` is read only for \`type: 'online'\`; embedded ${strType} has nowhere to write it, so it was ignored.`);
|
|
1329
1365
|
const options = framedObjectOptions(target, "media", opt, {
|
|
1330
1366
|
label: "Media",
|
|
1331
1367
|
kind: "media",
|
|
@@ -1411,8 +1447,7 @@ function addMediaDefinition(target, opt) {
|
|
|
1411
1447
|
assertConsecutiveMediaRids(mediaRid, msRid, coverRid);
|
|
1412
1448
|
target._slideObjects.push(slideData);
|
|
1413
1449
|
}
|
|
1414
|
-
|
|
1415
|
-
//#region src/gen/oxml/alternate-content.ts
|
|
1450
|
+
// src/gen/oxml/alternate-content.ts
|
|
1416
1451
|
/**
|
|
1417
1452
|
* An `mc:AlternateContent` envelope: a Choice for consumers that understand one namespace, and an
|
|
1418
1453
|
* optional Fallback for everyone else.
|
|
@@ -1435,50 +1470,7 @@ function alternateContentEl(opts) {
|
|
|
1435
1470
|
Requires: prefix
|
|
1436
1471
|
}, raw(opts.choice))), ...opts.fallback === void 0 ? [] : [raw(el("mc:Fallback", null, raw(opts.fallback)))]]);
|
|
1437
1472
|
}
|
|
1438
|
-
|
|
1439
|
-
//#region src/gen/drawingml/locks.ts
|
|
1440
|
-
const SHAPE_LOCK_ATTRS = [
|
|
1441
|
-
"noGrp",
|
|
1442
|
-
"noSelect",
|
|
1443
|
-
"noRot",
|
|
1444
|
-
"noChangeAspect",
|
|
1445
|
-
"noMove",
|
|
1446
|
-
"noResize",
|
|
1447
|
-
"noEditPoints",
|
|
1448
|
-
"noAdjustHandles",
|
|
1449
|
-
"noChangeArrowheads",
|
|
1450
|
-
"noChangeShapeType",
|
|
1451
|
-
"noTextEdit"
|
|
1452
|
-
];
|
|
1453
|
-
const PICTURE_LOCK_ATTRS = [
|
|
1454
|
-
"noGrp",
|
|
1455
|
-
"noSelect",
|
|
1456
|
-
"noRot",
|
|
1457
|
-
"noChangeAspect",
|
|
1458
|
-
"noMove",
|
|
1459
|
-
"noResize",
|
|
1460
|
-
"noEditPoints",
|
|
1461
|
-
"noAdjustHandles",
|
|
1462
|
-
"noChangeArrowheads",
|
|
1463
|
-
"noChangeShapeType",
|
|
1464
|
-
"noCrop"
|
|
1465
|
-
];
|
|
1466
|
-
const GRAPHIC_FRAME_LOCK_ATTRS = [
|
|
1467
|
-
"noGrp",
|
|
1468
|
-
"noDrilldown",
|
|
1469
|
-
"noSelect",
|
|
1470
|
-
"noChangeAspect",
|
|
1471
|
-
"noMove",
|
|
1472
|
-
"noResize"
|
|
1473
|
-
];
|
|
1474
|
-
const GROUP_SHAPE_LOCK_ATTRS = [
|
|
1475
|
-
"noGrp",
|
|
1476
|
-
"noSelect",
|
|
1477
|
-
"noRot",
|
|
1478
|
-
"noChangeAspect",
|
|
1479
|
-
"noMove",
|
|
1480
|
-
"noResize"
|
|
1481
|
-
];
|
|
1473
|
+
// src/gen/drawingml/locks.ts
|
|
1482
1474
|
/**
|
|
1483
1475
|
* Serialize an object-lock element (`a:spLocks` / `a:picLocks` / `a:graphicFrameLocks`).
|
|
1484
1476
|
* Only flags set to `true` AND valid for this element type are emitted; a flag set on an
|
|
@@ -1496,8 +1488,7 @@ function genXmlObjectLock(tag, allowed, locks, objectName) {
|
|
|
1496
1488
|
const set = allowed.filter((name) => lockMap[name] === true);
|
|
1497
1489
|
return set.length > 0 ? voidEl(tag, Object.fromEntries(set.map((name) => [name, "1"]))) : "";
|
|
1498
1490
|
}
|
|
1499
|
-
|
|
1500
|
-
//#region src/gen/slide/objects/image-extent.ts
|
|
1491
|
+
// src/gen/slide/objects/image-extent.ts
|
|
1501
1492
|
/**
|
|
1502
1493
|
* An image's natural size in pixels, measured from its embedded media.
|
|
1503
1494
|
*
|
|
@@ -1508,7 +1499,7 @@ function genXmlObjectLock(tag, allowed, locks, objectName) {
|
|
|
1508
1499
|
* @returns the natural size, or `null` when the media is not loaded or cannot be measured
|
|
1509
1500
|
*/
|
|
1510
1501
|
function imageNaturalSize(obj, slide) {
|
|
1511
|
-
const relData =
|
|
1502
|
+
const relData = slide._relsMedia.find((rel) => rel.rId === obj.imageRid)?.data;
|
|
1512
1503
|
return typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
1513
1504
|
}
|
|
1514
1505
|
/**
|
|
@@ -1552,14 +1543,13 @@ function resolveImageExtent(obj, slide, frame) {
|
|
|
1552
1543
|
drawnH: sizing.h ? getSmartParseNumber(sizing.h, "Y", slide._presLayout) : frameH
|
|
1553
1544
|
};
|
|
1554
1545
|
}
|
|
1555
|
-
|
|
1556
|
-
//#region src/gen/oxml/fmt-scheme.ts
|
|
1546
|
+
// src/gen/oxml/fmt-scheme.ts
|
|
1557
1547
|
/**
|
|
1558
1548
|
* pptx-ts: the `<a:fmtScheme>` block, shared by the two themes this library writes.
|
|
1559
1549
|
*
|
|
1560
1550
|
* The fill/line/effect/background style matrices that shape style indices (`<p:style>`) point
|
|
1561
|
-
* at. Fixed Office boilerplate: no caller data reaches it, so
|
|
1562
|
-
* `<a:fontScheme>` blocks beside it in `gen/pres/theme.ts
|
|
1551
|
+
* at. Fixed Office boilerplate: no caller data reaches it, so, unlike the `<a:clrScheme>` and
|
|
1552
|
+
* `<a:fontScheme>` blocks beside it in `gen/pres/theme.ts`, there is no escaping risk to remove
|
|
1563
1553
|
* by rebuilding it node by node, and it stays a raw literal rather than ~90 nested `el()` calls
|
|
1564
1554
|
* written for uniformity alone.
|
|
1565
1555
|
*
|
|
@@ -1570,8 +1560,7 @@ function resolveImageExtent(obj, slide, frame) {
|
|
|
1570
1560
|
* @raw-xml-asset
|
|
1571
1561
|
*/
|
|
1572
1562
|
const FMT_SCHEME_XML = "<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>";
|
|
1573
|
-
|
|
1574
|
-
//#region src/gen/chart/part-names.ts
|
|
1563
|
+
// src/gen/chart/part-names.ts
|
|
1575
1564
|
/**
|
|
1576
1565
|
* The names for the chart with package-wide id `globalId`.
|
|
1577
1566
|
* @param globalId - the chart's id, unique across every chart part in the package
|
|
@@ -1588,8 +1577,7 @@ function chartPartNames(globalId, isChartEx) {
|
|
|
1588
1577
|
workbookName: `Microsoft_Excel_Worksheet${globalId}.xlsx`
|
|
1589
1578
|
};
|
|
1590
1579
|
}
|
|
1591
|
-
|
|
1592
|
-
//#region src/gen/opc/core.ts
|
|
1580
|
+
// src/gen/opc/core.ts
|
|
1593
1581
|
/**
|
|
1594
1582
|
* pptx-ts: `docProps/core.xml`
|
|
1595
1583
|
*
|
|
@@ -1611,7 +1599,7 @@ const CORE_PROPS_NS = {
|
|
|
1611
1599
|
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance"
|
|
1612
1600
|
};
|
|
1613
1601
|
/**
|
|
1614
|
-
* Now, as `dcterms:W3CDTF` without milliseconds
|
|
1602
|
+
* Now, as `dcterms:W3CDTF` without milliseconds, the precision Office writes.
|
|
1615
1603
|
*
|
|
1616
1604
|
* Call it **once** per part and reuse the value for `created` and `modified`: two calls make a
|
|
1617
1605
|
* part whose two timestamps can disagree by a millisecond depending on when the build crossed a
|
|
@@ -1654,8 +1642,21 @@ function makeXmlCore(title, subject, author, revision) {
|
|
|
1654
1642
|
closePrefix: "\n "
|
|
1655
1643
|
});
|
|
1656
1644
|
}
|
|
1657
|
-
|
|
1658
|
-
|
|
1645
|
+
// src/gen/pres/table-styles.ts
|
|
1646
|
+
/** The style PowerPoint applies to a new table, which the part names as its default. */
|
|
1647
|
+
const DEFAULT_TABLE_STYLE = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
|
|
1648
|
+
/**
|
|
1649
|
+
* Create `ppt/tableStyles.xml`
|
|
1650
|
+
* @param definitions - the `a:tblStyle` elements the part carries, in order
|
|
1651
|
+
* @return {string} XML
|
|
1652
|
+
*/
|
|
1653
|
+
function makeXmlTableStyles(definitions) {
|
|
1654
|
+
return XML_DECL + "\r\n" + elOrVoid("a:tblStyleLst", {
|
|
1655
|
+
"xmlns:a": OOXML_NS.a,
|
|
1656
|
+
def: DEFAULT_TABLE_STYLE
|
|
1657
|
+
}, definitions.join(""));
|
|
1658
|
+
}
|
|
1659
|
+
// src/families/group.ts
|
|
1659
1660
|
/**
|
|
1660
1661
|
* pptx-ts: the group construct family
|
|
1661
1662
|
*
|
|
@@ -1674,8 +1675,7 @@ const groupFamily = {
|
|
|
1674
1675
|
}
|
|
1675
1676
|
}
|
|
1676
1677
|
};
|
|
1677
|
-
|
|
1678
|
-
//#region src/gen/drawingml/image.ts
|
|
1678
|
+
// src/gen/drawingml/image.ts
|
|
1679
1679
|
/**
|
|
1680
1680
|
* pptx-ts: DrawingML image sizing & cropping
|
|
1681
1681
|
*
|
|
@@ -1711,12 +1711,12 @@ const ImageSizingXml = {
|
|
|
1711
1711
|
const b = imgSize.h - (boxDim.y + boxDim.h);
|
|
1712
1712
|
if (l < 0 || r < 0 || t < 0 || b < 0) {
|
|
1713
1713
|
const over = [
|
|
1714
|
-
l < 0 && `x (${
|
|
1714
|
+
l < 0 && `x (${-l} past left edge)`,
|
|
1715
1715
|
r < 0 && `x+w (${-r} past right edge)`,
|
|
1716
1716
|
t < 0 && `y (${-t} past top edge)`,
|
|
1717
1717
|
b < 0 && `y+h (${-b} past bottom edge)`
|
|
1718
1718
|
].filter(Boolean).join(", ");
|
|
1719
|
-
throw new InvalidOptionError("image/crop-window-overflows", `addImage sizing.type 'crop': crop window overflows image bounds
|
|
1719
|
+
throw new InvalidOptionError("image/crop-window-overflows", `addImage sizing.type 'crop': crop window overflows image bounds: ${over}. Ensure x≥0, y≥0, x+w≤w, y+h≤h.`);
|
|
1720
1720
|
}
|
|
1721
1721
|
const lPerc = Math.round(PERCENT_SCALE * (l / imgSize.w));
|
|
1722
1722
|
const rPerc = Math.round(PERCENT_SCALE * (r / imgSize.w));
|
|
@@ -1732,12 +1732,12 @@ const ImageSizingXml = {
|
|
|
1732
1732
|
};
|
|
1733
1733
|
/**
|
|
1734
1734
|
* The blipFill children for a vector source the caller gave no `sizing` for: letterbox it to its
|
|
1735
|
-
* own aspect ratio inside its frame, the way `sizing: 'contain'` would
|
|
1735
|
+
* own aspect ratio inside its frame, the way `sizing: 'contain'` would. An SVG carries an
|
|
1736
1736
|
* intrinsic ratio, and stretching a glyph into a box that disagrees with it is never the intent.
|
|
1737
1737
|
*
|
|
1738
1738
|
* Returns `null` when the two ratios already agree, which is the overwhelmingly common case (a
|
|
1739
1739
|
* square icon in a square box). The caller then emits the plain `<a:stretch>` it always did, so
|
|
1740
|
-
* this default costs nothing
|
|
1740
|
+
* this default costs nothing (neither bytes nor a behaviour change) until it actually differs.
|
|
1741
1741
|
* @param imgSize - the vector's intrinsic size (viewBox or width/height)
|
|
1742
1742
|
* @param boxDim - the picture's displayed frame
|
|
1743
1743
|
* @returns the `<a:srcRect>` + `<a:stretch>` children, or `null` if no letterboxing is needed
|
|
@@ -1758,8 +1758,7 @@ function genXmlImageCrop(crop, objectName) {
|
|
|
1758
1758
|
const where = objectName ? ` for image "${objectName}"` : "";
|
|
1759
1759
|
return genXmlImageCropRect(crop, "addImage", where) + STRETCH;
|
|
1760
1760
|
}
|
|
1761
|
-
|
|
1762
|
-
//#region src/gen/slide/objects/image.ts
|
|
1761
|
+
// src/gen/slide/objects/image.ts
|
|
1763
1762
|
/**
|
|
1764
1763
|
* pptx-ts: image slide-object serialization
|
|
1765
1764
|
*
|
|
@@ -1779,7 +1778,7 @@ function renderImageObject(ctx) {
|
|
|
1779
1778
|
let drawnH = frameH;
|
|
1780
1779
|
const { sizing, rounding } = itemOpts;
|
|
1781
1780
|
let strSlideXml = "";
|
|
1782
|
-
const mediaRel =
|
|
1781
|
+
const mediaRel = slide._relsMedia.find((rel) => rel.rId === slideItemObj.imageRid);
|
|
1783
1782
|
const naturalSize = () => imageNaturalSize(slideItemObj, slide);
|
|
1784
1783
|
const imgOpts = itemOpts;
|
|
1785
1784
|
const imgLink = slideItemObj.hyperlink;
|
|
@@ -1790,7 +1789,7 @@ function renderImageObject(ctx) {
|
|
|
1790
1789
|
noChangeAspect: true,
|
|
1791
1790
|
...imgOpts.objectLock
|
|
1792
1791
|
}, imgOpts.objectName)), { openPrefix: " " });
|
|
1793
|
-
strSlideXml += el("p:nvPr", null, raw(genXmlPlaceholder(placeholderObj)), { openPrefix: " " });
|
|
1792
|
+
strSlideXml += el("p:nvPr", null, raw(genXmlPlaceholder(placeholderObj, statedPlaceholderBinding(itemOpts.placeholder))), { openPrefix: " " });
|
|
1794
1793
|
strSlideXml += " </p:nvPicPr>";
|
|
1795
1794
|
const blipEffects = (alphaPrefix) => [
|
|
1796
1795
|
mapStated(imgOpts.transparency, (transparency) => raw(voidEl("a:alphaModFix", { amt: transparencyToAlpha(transparency) }, { openPrefix: alphaPrefix }))) ?? null,
|
|
@@ -1865,8 +1864,7 @@ function renderImageObject(ctx) {
|
|
|
1865
1864
|
strSlideXml += "</p:pic>";
|
|
1866
1865
|
return strSlideXml;
|
|
1867
1866
|
}
|
|
1868
|
-
|
|
1869
|
-
//#region src/families/image.ts
|
|
1867
|
+
// src/families/image.ts
|
|
1870
1868
|
const imageFamily = {
|
|
1871
1869
|
name: "image",
|
|
1872
1870
|
authors: { addImage(slide, options) {
|
|
@@ -1877,8 +1875,7 @@ const imageFamily = {
|
|
|
1877
1875
|
} },
|
|
1878
1876
|
renderers: { ["image"]: renderImageObject }
|
|
1879
1877
|
};
|
|
1880
|
-
|
|
1881
|
-
//#region src/package/parts/notes.ts
|
|
1878
|
+
// src/package/parts/notes.ts
|
|
1882
1879
|
const notesContributor = {
|
|
1883
1880
|
order: 10,
|
|
1884
1881
|
parts: {
|
|
@@ -1907,8 +1904,7 @@ const notesContributor = {
|
|
|
1907
1904
|
}
|
|
1908
1905
|
}
|
|
1909
1906
|
};
|
|
1910
|
-
|
|
1911
|
-
//#region src/gen/define/notes.ts
|
|
1907
|
+
// src/gen/define/notes.ts
|
|
1912
1908
|
/**
|
|
1913
1909
|
* Adds Notes to a slide.
|
|
1914
1910
|
* @param {PresSlideInternal} `target` slide object
|
|
@@ -1926,8 +1922,7 @@ function addNotesDefinition(target, notes) {
|
|
|
1926
1922
|
text: runs
|
|
1927
1923
|
});
|
|
1928
1924
|
}
|
|
1929
|
-
|
|
1930
|
-
//#region src/families/notes.ts
|
|
1925
|
+
// src/families/notes.ts
|
|
1931
1926
|
/**
|
|
1932
1927
|
* pptx-ts: the speaker-notes construct family
|
|
1933
1928
|
*
|
|
@@ -1942,8 +1937,7 @@ const notesFamily = {
|
|
|
1942
1937
|
} },
|
|
1943
1938
|
parts: notesContributor
|
|
1944
1939
|
};
|
|
1945
|
-
|
|
1946
|
-
//#region src/gen/define/shape.ts
|
|
1940
|
+
// src/gen/define/shape.ts
|
|
1947
1941
|
/**
|
|
1948
1942
|
* Map of common friendly shape names users pass as bare strings to their
|
|
1949
1943
|
* valid OOXML preset values. PowerPoint can't parse the friendly spellings
|
|
@@ -1989,8 +1983,7 @@ function addShapeDefinition(target, shapeName, opts) {
|
|
|
1989
1983
|
if (typeof options.fill === "object" && resolveFillKind(options.fill) === "image") registerImageFillMedia(target, options.fill);
|
|
1990
1984
|
target._slideObjects.push(newObject);
|
|
1991
1985
|
}
|
|
1992
|
-
|
|
1993
|
-
//#region src/families/shape.ts
|
|
1986
|
+
// src/families/shape.ts
|
|
1994
1987
|
const shapeFamily = {
|
|
1995
1988
|
name: "shape",
|
|
1996
1989
|
authors: { addShape(slide, shapeName, options) {
|
|
@@ -2011,8 +2004,7 @@ const shapeFamily = {
|
|
|
2011
2004
|
}
|
|
2012
2005
|
}
|
|
2013
2006
|
};
|
|
2014
|
-
|
|
2015
|
-
//#region src/gen/slide/objects/text.ts
|
|
2007
|
+
// src/gen/slide/objects/text.ts
|
|
2016
2008
|
/**
|
|
2017
2009
|
* Render a `text` / `placeholder` slide object to its `<p:sp>` XML.
|
|
2018
2010
|
*/
|
|
@@ -2024,10 +2016,11 @@ function renderTextObject(ctx) {
|
|
|
2024
2016
|
strSlideXml += "<p:nvSpPr>" + cNvPrEl(shapeId, txtOpts.objectName, txtOpts.altText || "", cNvPrHyperlink(txtOpts.hyperlink));
|
|
2025
2017
|
{
|
|
2026
2018
|
const spLockXml = genXmlObjectLock("a:spLocks", SHAPE_LOCK_ATTRS, txtOpts.objectLock, txtOpts.objectName);
|
|
2027
|
-
const cNvSpPrAttrs = { txBox: xsdBoolIfTrue(txtOpts
|
|
2019
|
+
const cNvSpPrAttrs = { txBox: xsdBoolIfTrue(txtOpts.isTextBox) };
|
|
2028
2020
|
strSlideXml += elOrVoid("p:cNvSpPr", cNvSpPrAttrs, spLockXml);
|
|
2029
2021
|
}
|
|
2030
|
-
|
|
2022
|
+
const isPlaceholderDef = slideItemObj._type === "placeholder";
|
|
2023
|
+
strSlideXml += el("p:nvPr", null, raw(genXmlPlaceholder(isPlaceholderDef || placeholderObj == null && itemOpts._placeholderType ? slideItemObj : placeholderObj, statedPlaceholderBinding(itemOpts.placeholder), isPlaceholderDef)));
|
|
2031
2024
|
strSlideXml += "</p:nvSpPr><p:spPr>";
|
|
2032
2025
|
strSlideXml += xfrmEl("a:xfrm", {
|
|
2033
2026
|
x,
|
|
@@ -2042,7 +2035,7 @@ function renderTextObject(ctx) {
|
|
|
2042
2035
|
if (itemOpts.line) strSlideXml += genXmlShapeLine(itemOpts.line);
|
|
2043
2036
|
if (itemOpts.shadow && itemOpts.shadow.type !== "none") strSlideXml += createShadowEffectLst(itemOpts.shadow, DEF_TEXT_SHADOW);
|
|
2044
2037
|
strSlideXml += "</p:spPr>";
|
|
2045
|
-
strSlideXml += genXmlTextBody(slideItemObj);
|
|
2038
|
+
strSlideXml += genXmlTextBody(slideItemObj, slideTextColor(slide));
|
|
2046
2039
|
strSlideXml += "</p:sp>";
|
|
2047
2040
|
if (objectHasMath(slideItemObj)) return alternateContentEl({
|
|
2048
2041
|
requires: {
|
|
@@ -2053,8 +2046,7 @@ function renderTextObject(ctx) {
|
|
|
2053
2046
|
});
|
|
2054
2047
|
return strSlideXml;
|
|
2055
2048
|
}
|
|
2056
|
-
|
|
2057
|
-
//#region src/families/text.ts
|
|
2049
|
+
// src/families/text.ts
|
|
2058
2050
|
/**
|
|
2059
2051
|
* Refuse a `text` that is none of the forms the signature takes. A single run object,
|
|
2060
2052
|
* `{ text: 'x' }`, is the one a caller reaches for, and it failed inside the definer with a
|
|
@@ -2081,16 +2073,14 @@ const textFamily = {
|
|
|
2081
2073
|
["text"]: renderTextObject
|
|
2082
2074
|
}
|
|
2083
2075
|
};
|
|
2084
|
-
|
|
2085
|
-
//#region src/families/animations.ts
|
|
2076
|
+
// src/families/animations.ts
|
|
2086
2077
|
const animationsFamily = {
|
|
2087
2078
|
name: "animations",
|
|
2088
2079
|
authors: { addAnimation(slide, options) {
|
|
2089
2080
|
slide._animations.push(options);
|
|
2090
2081
|
} }
|
|
2091
2082
|
};
|
|
2092
|
-
|
|
2093
|
-
//#region src/gen/chart/chart-kind.ts
|
|
2083
|
+
// src/gen/chart/chart-kind.ts
|
|
2094
2084
|
/** Both bubble variants (`<c:bubbleChart>`), which differ only by `<c:bubble3D>`. */
|
|
2095
2085
|
function isBubbleChart(type) {
|
|
2096
2086
|
return type === "bubble" || type === "bubble3D";
|
|
@@ -2160,8 +2150,7 @@ const STOCK_STYLE_SPEC = {
|
|
|
2160
2150
|
upDownBars: true
|
|
2161
2151
|
}
|
|
2162
2152
|
};
|
|
2163
|
-
|
|
2164
|
-
//#region src/gen/chart/data-refs.ts
|
|
2153
|
+
// src/gen/chart/data-refs.ts
|
|
2165
2154
|
/**
|
|
2166
2155
|
* pptx-ts: Chart Series-Data ↔ Worksheet-Cell Mapping
|
|
2167
2156
|
*
|
|
@@ -2169,7 +2158,7 @@ const STOCK_STYLE_SPEC = {
|
|
|
2169
2158
|
* accessors over the normalized (internal) chart-series arrays, and the builders that
|
|
2170
2159
|
* turn a (column, row) into an absolute reference into the chart's embedded `Sheet1`.
|
|
2171
2160
|
* The embedded-workbook builder ({@link ../chart/embed-xlsx}) writes the cells; the
|
|
2172
|
-
* chart-XML builder ({@link ../chart/chart-xml}) points `<c:f>` formulas back at them
|
|
2161
|
+
* chart-XML builder ({@link ../chart/chart-xml}) points `<c:f>` formulas back at them,
|
|
2173
2162
|
* so this mapping lives in one place to keep column letters and `$`-anchoring from
|
|
2174
2163
|
* drifting between the two sides.
|
|
2175
2164
|
*/
|
|
@@ -2328,8 +2317,7 @@ function worksheetLayout(rel) {
|
|
|
2328
2317
|
* @param count - how many categories the series carries
|
|
2329
2318
|
*/
|
|
2330
2319
|
const categoryRange = (sheet, count) => sheetRangeRef(sheet.labelCols, 2, sheet.labelCols, count + 1);
|
|
2331
|
-
|
|
2332
|
-
//#region src/gen/chart/chart-stroke.ts
|
|
2320
|
+
// src/gen/chart/chart-stroke.ts
|
|
2333
2321
|
/**
|
|
2334
2322
|
* pptx-ts: folding a chart's older stroke spellings onto {@link StrokeProps}.
|
|
2335
2323
|
*
|
|
@@ -2419,7 +2407,7 @@ function axisLineStroke(opts, axis) {
|
|
|
2419
2407
|
* @param option - the option path to name in a diagnostic, as the caller spells it
|
|
2420
2408
|
*/
|
|
2421
2409
|
function scrubGridLine(glOpts, option = "chart.gridLine") {
|
|
2422
|
-
if (
|
|
2410
|
+
if (gridLineSuppressed(glOpts)) return;
|
|
2423
2411
|
const width = glOpts.width ?? glOpts.size;
|
|
2424
2412
|
if (width !== void 0 && (!Number.isFinite(Number(width)) || width <= 0)) {
|
|
2425
2413
|
warn("chart/invalid-grid-line-size", `${option}.width must be greater than 0.`);
|
|
@@ -2443,8 +2431,7 @@ function scrubGridLine(glOpts, option = "chart.gridLine") {
|
|
|
2443
2431
|
delete glOpts.cap;
|
|
2444
2432
|
}
|
|
2445
2433
|
}
|
|
2446
|
-
|
|
2447
|
-
//#region src/gen/chart/chart-parts.ts
|
|
2434
|
+
// src/gen/chart/chart-parts.ts
|
|
2448
2435
|
/**
|
|
2449
2436
|
* The six `c:show*` flags every `<c:dLbls>` carries, in schema order, as `XmlChild`s for the
|
|
2450
2437
|
* parent's child list. Eight `<c:dLbls>` builders across five modules wrote all six out by
|
|
@@ -2470,15 +2457,15 @@ function dLblShowFlags(flags) {
|
|
|
2470
2457
|
* The data-label run properties, in the attribute order the scatter and custom-label paths
|
|
2471
2458
|
* emit: `sz, b, i, u, strike`.
|
|
2472
2459
|
*
|
|
2473
|
-
* There is a second ordering in this file
|
|
2474
|
-
* {@link chartDataLabels} and by the bubble plot
|
|
2460
|
+
* There is a second ordering in this file, `b, i, strike, sz, u`, used by
|
|
2461
|
+
* {@link chartDataLabels} and by the bubble plot, and the two are **deliberately not
|
|
2475
2462
|
* merged**. Attribute order carries no meaning in XML, so either is correct and a reader is
|
|
2476
2463
|
* right to want one; but merging them moves bytes in a refactor whose whole claim is that it
|
|
2477
2464
|
* does not, and the byte-identity gate is what makes that claim checkable. Unifying the
|
|
2478
2465
|
* spelling is a decision to take on its own, with its own re-baseline.
|
|
2479
2466
|
*
|
|
2480
2467
|
* `over` layers a series' own `seriesOptions` entry on top with `??`, leaving the chart-level
|
|
2481
|
-
* reading below it exactly as it was
|
|
2468
|
+
* reading below it exactly as it was: a series that states nothing produces the same bytes.
|
|
2482
2469
|
* @param opts - the chart's normalized options
|
|
2483
2470
|
* @param over - this series' `seriesOptions` entry, whose stated fields win over the chart's
|
|
2484
2471
|
*/
|
|
@@ -2550,7 +2537,7 @@ function labelRun(opts, text, over) {
|
|
|
2550
2537
|
* The `<c:txPr>` a data-label block wraps its run properties in: an empty `<a:bodyPr>`, an empty
|
|
2551
2538
|
* `<a:lstStyle>`, then one `<a:p>` carrying the `<a:pPr>` the caller built.
|
|
2552
2539
|
*
|
|
2553
|
-
* Five sites spelled this out byte-identically
|
|
2540
|
+
* Five sites spelled this out byte-identically: the shared `<c:dLbls>` builder, the bubble,
|
|
2554
2541
|
* category-axis and pie plots, and the pie's plot-level block. The axis one in `chart-axes.ts`
|
|
2555
2542
|
* is deliberately NOT this: it carries a rotation on the `bodyPr` and an `<a:endParaRPr>` after
|
|
2556
2543
|
* the `<a:pPr>`.
|
|
@@ -2598,7 +2585,7 @@ function c15LeaderLinesExt(val) {
|
|
|
2598
2585
|
* This and {@link labelFontAttrs} read the same five options and read them the same way:
|
|
2599
2586
|
* `over?.X ?? opts.X ?? DEFAULT`. Attribute order is the only difference left between them.
|
|
2600
2587
|
*
|
|
2601
|
-
* They disagreed on the operator once
|
|
2588
|
+
* They disagreed on the operator once (`??` here against `||` there), and which one a chart
|
|
2602
2589
|
* reached was decided by its type and its label format, so `dataLabelFontSize: 0` had three
|
|
2603
2590
|
* answers: a bar warned and clamped, a pie dropped the value with no diagnostic at all, and an
|
|
2604
2591
|
* `XY` scatter, which reaches both builders, emitted `sz="100"` on one label block and
|
|
@@ -2653,7 +2640,7 @@ function validTimeUnit(value, optionName) {
|
|
|
2653
2640
|
* `undefined` when the caller's value is not one.
|
|
2654
2641
|
*
|
|
2655
2642
|
* `catAxisLabelFrequency` and `serAxisLabelFrequency` were typed as free-form strings and
|
|
2656
|
-
* emitted verbatim, so `'every other'` reached `<c:tickLblSkip val="every other"
|
|
2643
|
+
* emitted verbatim, so `'every other'` reached `<c:tickLblSkip val="every other"/>`, and the
|
|
2657
2644
|
* type also rejected the natural `2`. Same shape as {@link validTimeUnit} beside it: warn and
|
|
2658
2645
|
* emit nothing rather than write a value outside the attribute's own type.
|
|
2659
2646
|
* @param value - the caller's value, a number or a numeric string
|
|
@@ -2673,7 +2660,7 @@ function positiveIntAttr(value, optionName) {
|
|
|
2673
2660
|
* for a rule, and `defaultRule` when the caller stated neither.
|
|
2674
2661
|
*
|
|
2675
2662
|
* The two axis builders each spelled this decision out, and both opened it with
|
|
2676
|
-
* `typeof value === 'number'
|
|
2663
|
+
* `typeof value === 'number'`, the one numeric guard in the file that `NaN` passes, since every
|
|
2677
2664
|
* other numeric axis option is guarded by truthiness. `{ valAxisCrossesAt: NaN }` therefore
|
|
2678
2665
|
* emitted `<c:crossesAt val="NaN"/>`, and `ST_Double` has no such value.
|
|
2679
2666
|
* @param value - the caller's `*AxisCrossesAt`: a position, a `ST_Crosses` rule, or nothing
|
|
@@ -2719,9 +2706,8 @@ function resolveChartPalette(opts) {
|
|
|
2719
2706
|
* Every palette lookup in this directory goes through here so that a deck with more series or
|
|
2720
2707
|
* data points than the palette has entries still emits the same bytes on every build.
|
|
2721
2708
|
*/
|
|
2722
|
-
function paletteColor(palette, idx
|
|
2723
|
-
|
|
2724
|
-
return palette[idx % palette.length] ?? fallback;
|
|
2709
|
+
function paletteColor(palette, idx) {
|
|
2710
|
+
return palette[idx % palette.length] ?? "000000";
|
|
2725
2711
|
}
|
|
2726
2712
|
const DEF_GRIDLINE_COLOR = DEF_CHART_GRIDLINE.color ?? "888888";
|
|
2727
2713
|
/**
|
|
@@ -2740,12 +2726,12 @@ function seriesDash(opts, serIndex) {
|
|
|
2740
2726
|
/**
|
|
2741
2727
|
* Fill fragment for a `chartColors`-derived series/line/marker colour.
|
|
2742
2728
|
*
|
|
2743
|
-
* A `'transparent'` entry means "no fill"
|
|
2744
|
-
* stroke
|
|
2729
|
+
* A `'transparent'` entry means "no fill" (an invisible series, connecting line, or marker
|
|
2730
|
+
* stroke) and maps to `<a:noFill/>`. Any real colour goes through the normal solid-fill path.
|
|
2745
2731
|
* The series and marker *fill* paths already special-case `'transparent'`; without this the
|
|
2746
2732
|
* *stroke* paths (`<a:ln>` on the series line and marker border) would instead pass the literal
|
|
2747
2733
|
* `'transparent'` through colour validation, warn "not a valid scheme color or hex RGB", and
|
|
2748
|
-
* render as black
|
|
2734
|
+
* render as black, leaving a stray black line/border where a transparent series was requested.
|
|
2749
2735
|
*/
|
|
2750
2736
|
function chartColorLineFill(color) {
|
|
2751
2737
|
return color === "transparent" ? voidEl("a:noFill") : genXmlColorSelection(color);
|
|
@@ -2756,7 +2742,7 @@ function chartColorLineFill(color) {
|
|
|
2756
2742
|
* otherwise.
|
|
2757
2743
|
*
|
|
2758
2744
|
* Read against {@link chartColorLineFill}, which is the same decision for a *stroke* and stops
|
|
2759
|
-
* one step earlier
|
|
2745
|
+
* one step earlier: a stroke has no opacity option to fold in. Three plot builders (bubble,
|
|
2760
2746
|
* scatter, and the whole category-axis family) each carried this expression verbatim, down to
|
|
2761
2747
|
* the diagnostic code and the option name in its message, which is what made the `transparent`
|
|
2762
2748
|
* arm easy to add to one and forget in another.
|
|
@@ -2771,7 +2757,7 @@ function seriesFill(opts, serColor) {
|
|
|
2771
2757
|
return el("a:solidFill", null, raw(createColorElement(serColor, alpha)));
|
|
2772
2758
|
}
|
|
2773
2759
|
/**
|
|
2774
|
-
* One plotted series' stroke
|
|
2760
|
+
* One plotted series' stroke (a width, this series' dash, the palette colour and a round join),
|
|
2775
2761
|
* or `<a:noFill/>` when the caller asked for no line at all.
|
|
2776
2762
|
*
|
|
2777
2763
|
* Three plot builders had this, differing only in whether a per-series `lineSize` could override
|
|
@@ -2852,7 +2838,7 @@ function serMarker(opts, markerColor, seriesColor) {
|
|
|
2852
2838
|
* its element: `<a:latin>` covers Latin/ASCII, `<a:ea>` covers East Asian, and
|
|
2853
2839
|
* `<a:cs>` covers complex scripts. Emitting `<a:latin>` alone leaves East Asian
|
|
2854
2840
|
* (e.g. Chinese) and complex-script glyphs falling back to the theme font, so a
|
|
2855
|
-
* user-specified font never takes effect for that text
|
|
2841
|
+
* user-specified font never takes effect for that text, most visibly on
|
|
2856
2842
|
* PowerPoint for Mac. Stamping the same typeface onto all three classes is what
|
|
2857
2843
|
* choosing a font in PowerPoint's UI does.
|
|
2858
2844
|
* @param {string} typeface - font face name
|
|
@@ -2886,7 +2872,7 @@ function genXmlTitle(opts, chartX, chartY) {
|
|
|
2886
2872
|
const runChildren = genXmlColorSelection(namedColorOr(opts.color, DEF_FONT_COLOR, "chart text color")) + createChartTextFonts(opts.fontFace ?? "Arial");
|
|
2887
2873
|
/**
|
|
2888
2874
|
* Fold a slide-relative offset into the fraction-of-chart value `c:x`/`c:y` want, or
|
|
2889
|
-
* `undefined` when it does not read as a finite number
|
|
2875
|
+
* `undefined` when it does not read as a finite number: `ST_Double` has no `NaN`, and
|
|
2890
2876
|
* omitting the axis is what CT_ManualLayout already means by "leave this one automatic".
|
|
2891
2877
|
*/
|
|
2892
2878
|
const edgeFraction = (offset) => {
|
|
@@ -2900,7 +2886,7 @@ function genXmlTitle(opts, chartX, chartY) {
|
|
|
2900
2886
|
* The chart's own offset along one axis, in inches, to fold into the caller's `titlePos`.
|
|
2901
2887
|
*
|
|
2902
2888
|
* Resolved here rather than by the caller so the warning fires only where the value is
|
|
2903
|
-
* actually used
|
|
2889
|
+
* actually used. A chart with `showTitle` and no `titlePos` folds nothing and says nothing.
|
|
2904
2890
|
*/
|
|
2905
2891
|
const chartOffset = (value, axis) => {
|
|
2906
2892
|
const inches = chartCoordInches(value);
|
|
@@ -3033,7 +3019,7 @@ function chartDataLabels(opts, leaderLines) {
|
|
|
3033
3019
|
});
|
|
3034
3020
|
}
|
|
3035
3021
|
/**
|
|
3036
|
-
* An `<a:solidFill>` of the theme text colour dimmed towards the background
|
|
3022
|
+
* An `<a:solidFill>` of the theme text colour dimmed towards the background: the grey the chart
|
|
3037
3023
|
* furniture (stock hi-low lines and up/down bars, the data-table grid) is drawn in.
|
|
3038
3024
|
* `lumMod`/`lumOff` are the two halves of one dimming: how much of the luminance survives, and
|
|
3039
3025
|
* how much white is mixed back in.
|
|
@@ -3061,7 +3047,7 @@ function dimmedTextLine(lumMod, lumOff) {
|
|
|
3061
3047
|
* gaps and are skipped silently (a sparse, idx-keyed cache is valid).
|
|
3062
3048
|
*
|
|
3063
3049
|
* **PowerPoint is the only oracle for this.** `<c:v>` is `s:ST_Xstring` in the schema, not
|
|
3064
|
-
* `xsd:double
|
|
3050
|
+
* `xsd:double`. Nothing above is a schema violation, and the OpenXmlValidator reports every one
|
|
3065
3051
|
* of those three packages clean. An *empty* `<c:v>` is the case that shows why the distinction is
|
|
3066
3052
|
* worth stating rather than reasoning about: it looks equally invalid and it is not, opening
|
|
3067
3053
|
* cleanly and reading back as an empty point. See `pieValues` in
|
|
@@ -3197,7 +3183,7 @@ function makeCustomDLblXml(idx, text, opts) {
|
|
|
3197
3183
|
]);
|
|
3198
3184
|
}
|
|
3199
3185
|
/**
|
|
3200
|
-
* The `<a:ln>` a chart-level `dataBorder` paints around every data point
|
|
3186
|
+
* The `<a:ln>` a chart-level `dataBorder` paints around every data point: the bubble, the
|
|
3201
3187
|
* pie slice, the bar.
|
|
3202
3188
|
*
|
|
3203
3189
|
* A near-sibling of {@link createChartBorderLine} rather than the same thing, and the three
|
|
@@ -3225,7 +3211,7 @@ function createDataBorderLine(dataBorder, cap) {
|
|
|
3225
3211
|
* caller asked for none. See {@link createDataBorderLine} for why the two are separate.
|
|
3226
3212
|
*
|
|
3227
3213
|
* `type: 'dash'` here means the `dash` preset, not the `sysDash` a table border's `type`
|
|
3228
|
-
* resolves to
|
|
3214
|
+
* resolves to. A chart border has no `dashType` of its own to name a preset with, so the
|
|
3229
3215
|
* three-way switch is the whole vocabulary and it picks the plain one.
|
|
3230
3216
|
* @param border - the chart's `border` (`type`, `color`, `width`, `transparency`)
|
|
3231
3217
|
*/
|
|
@@ -3383,8 +3369,8 @@ function xySeriesRefs(chartType, obj, data, opts, sheet, valFmtCode) {
|
|
|
3383
3369
|
* A `<c:cat>` category reference: the `<c:f>` formula plus the `<c:numCache>`/`<c:strCache>` that
|
|
3384
3370
|
* mirrors the label cells it points at.
|
|
3385
3371
|
*
|
|
3386
|
-
* `kind` picks the cache: `'num'` for numeric categories
|
|
3387
|
-
* PowerPoint renders them as dates rather than serial numbers
|
|
3372
|
+
* `kind` picks the cache: `'num'` for numeric categories (dates, which need a `<c:formatCode>` so
|
|
3373
|
+
* PowerPoint renders them as dates rather than serial numbers) and `'str'` for text ones. Stock
|
|
3388
3374
|
* and cat-axis each carried both arms of that choice, and surface carried the string one, five
|
|
3389
3375
|
* copies of the same `<c:f>` + `<c:ptCount>` + `<c:pt idx>` loop.
|
|
3390
3376
|
*
|
|
@@ -3393,11 +3379,12 @@ function xySeriesRefs(chartType, obj, data, opts, sheet, valFmtCode) {
|
|
|
3393
3379
|
* different spelling.
|
|
3394
3380
|
* @param kind - `num` for a numeric (date) category cache, `str` for a text one
|
|
3395
3381
|
* @param ref - the `<c:f>` formula
|
|
3396
|
-
* @param labels - the category labels, in order; escaped on the way into `<c:v
|
|
3382
|
+
* @param labels - the category labels, in order; escaped on the way into `<c:v>`. A blank one has no
|
|
3383
|
+
* point in a numeric cache, whose `<c:v>` must hold a number, as {@link numCachePt} leaves a gap.
|
|
3397
3384
|
* @param formatCode - the cached `<c:formatCode>`; numeric caches only
|
|
3398
3385
|
*/
|
|
3399
3386
|
function catRefBlock(kind, ref, labels, formatCode) {
|
|
3400
|
-
const points = labels.map((label, idx) => el("c:pt", { idx }, raw(el("c:v", null, label)))).join("");
|
|
3387
|
+
const points = labels.map((label, idx) => kind === "num" && String(label ?? "").trim() === "" ? "" : el("c:pt", { idx }, raw(el("c:v", null, label)))).join("");
|
|
3401
3388
|
const cache = el(`c:${kind}Cache`, null, [formatCode === void 0 ? null : raw(el("c:formatCode", null, formatCode)), raw(voidEl("c:ptCount", { val: labels.length }) + points)]);
|
|
3402
3389
|
return el(`c:${kind}Ref`, null, [raw(el("c:f", null, ref)), raw(cache)]);
|
|
3403
3390
|
}
|
|
@@ -3406,13 +3393,13 @@ function catRefBlock(kind, ref, labels, formatCode) {
|
|
|
3406
3393
|
* it points at.
|
|
3407
3394
|
*
|
|
3408
3395
|
* Scatter and bubble each carried their own copy of this twice over, four near-identical
|
|
3409
|
-
* twelve-line blocks, and bubble's per-point sizes were a fifth
|
|
3396
|
+
* twelve-line blocks, and bubble's per-point sizes were a fifth: the same block under a third
|
|
3410
3397
|
* wrapping tag with a constant format code. `values` is the exact point list to cache, so the
|
|
3411
3398
|
* caller decides what a gap is: the Y series is emitted against the X series' length (a caller
|
|
3412
|
-
* may supply fewer Y values than X
|
|
3399
|
+
* may supply fewer Y values than X, e.g. a timeline with only the first few months filled in), and
|
|
3413
3400
|
* the shorter array's tail arrives here as `undefined`, which {@link numCachePt} skips.
|
|
3414
3401
|
*
|
|
3415
|
-
* `ptCount` is the length of the cached *range*
|
|
3402
|
+
* `ptCount` is the length of the cached *range* (the number of cells `ref` spans), which is not
|
|
3416
3403
|
* always `values.length`. A category chart caches one column against the chart's category count
|
|
3417
3404
|
* and may hold fewer values than that, so it states the count explicitly; scatter and bubble pad
|
|
3418
3405
|
* their arrays to the range instead and let the default stand. Both spellings mean the same
|
|
@@ -3427,9 +3414,9 @@ function catRefBlock(kind, ref, labels, formatCode) {
|
|
|
3427
3414
|
* @param ref - the `<c:f>` formula, from {@link sheetRangeRef} or written inline
|
|
3428
3415
|
* @param formatCode - the cached `<c:formatCode>`
|
|
3429
3416
|
* @param values - the points to cache, in order; `null`/`undefined` entries are gaps
|
|
3430
|
-
* @param ptCount - cells spanned by `ref
|
|
3417
|
+
* @param ptCount - cells spanned by `ref`
|
|
3431
3418
|
*/
|
|
3432
|
-
function numRefBlock(tag, ref, formatCode, values, ptCount
|
|
3419
|
+
function numRefBlock(tag, ref, formatCode, values, ptCount) {
|
|
3433
3420
|
const numCache = el("c:numCache", null, [
|
|
3434
3421
|
raw(el("c:formatCode", null, formatCode)),
|
|
3435
3422
|
raw(voidEl("c:ptCount", { val: ptCount })),
|
|
@@ -3438,8 +3425,7 @@ function numRefBlock(tag, ref, formatCode, values, ptCount = values.length) {
|
|
|
3438
3425
|
const numRef = el("c:numRef", null, [raw(el("c:f", null, ref)), raw(numCache)]);
|
|
3439
3426
|
return el(tag, null, raw(numRef));
|
|
3440
3427
|
}
|
|
3441
|
-
|
|
3442
|
-
//#region src/gen/chart/chart-axes.ts
|
|
3428
|
+
// src/gen/chart/chart-axes.ts
|
|
3443
3429
|
/**
|
|
3444
3430
|
* pptx-ts: Chart Axis Assembly
|
|
3445
3431
|
*
|
|
@@ -3613,20 +3599,39 @@ function makeCatAxis(opts, axisId, valAxisId) {
|
|
|
3613
3599
|
]);
|
|
3614
3600
|
}
|
|
3615
3601
|
/**
|
|
3602
|
+
* A value-axis bound as the axis can carry it: `undefined` when the axis is logarithmic and the
|
|
3603
|
+
* bound is not above 0, with a warning, so the axis scales itself instead.
|
|
3604
|
+
*
|
|
3605
|
+
* PowerPoint refuses a whole deck (0x80070570) over one chart whose `<c:logBase>` sits beside a
|
|
3606
|
+
* `<c:min val="0"/>`: a log axis has no 0 to start from. The check is here rather than in
|
|
3607
|
+
* `addChartDefinition` because a `valAxes[i]` entry is spread over the chart's options at emit
|
|
3608
|
+
* time, so a log base and a bound can each come from a different bag.
|
|
3609
|
+
* @param opts - the axis's options, overrides already applied
|
|
3610
|
+
* @param key - which bound
|
|
3611
|
+
*/
|
|
3612
|
+
function logAxisBound(opts, key) {
|
|
3613
|
+
const bound = opts[key];
|
|
3614
|
+
if (bound == null) return void 0;
|
|
3615
|
+
if (opts.valAxisLogScaleBase && bound <= 0) {
|
|
3616
|
+
warn("chart/option-out-of-range", `"${key}" must be above 0 on a logarithmic axis; ignoring ${bound} so the axis scales itself.`);
|
|
3617
|
+
return;
|
|
3618
|
+
}
|
|
3619
|
+
return bound;
|
|
3620
|
+
}
|
|
3621
|
+
/**
|
|
3616
3622
|
* Create Value Axis (Used by `bar3D`)
|
|
3617
3623
|
* @param {ChartOptsInternal} opts - chart options
|
|
3618
3624
|
* @param {string} valAxisId - value
|
|
3619
3625
|
* @return {string} XML
|
|
3620
3626
|
*/
|
|
3621
3627
|
function makeValAxis(opts, valAxisId) {
|
|
3622
|
-
|
|
3623
|
-
if (valAxisId === "2094734553") axisPos = "r";
|
|
3628
|
+
const axisPos = valAxisId === "2094734552" ? opts.barDir === "col" ? "l" : "b" : "r";
|
|
3624
3629
|
const crossAxId = valAxisId === "2094734552" ? AXIS_ID_CATEGORY_PRIMARY : AXIS_ID_CATEGORY_SECONDARY;
|
|
3625
3630
|
const scaling = el("c:scaling", null, [
|
|
3626
3631
|
opts.valAxisLogScaleBase ? raw(voidEl("c:logBase", { val: opts.valAxisLogScaleBase })) : null,
|
|
3627
3632
|
raw(voidEl("c:orientation", { val: opts.valAxisOrientation || "minMax" })),
|
|
3628
|
-
opts
|
|
3629
|
-
opts
|
|
3633
|
+
logAxisBound(opts, "valAxisMaxVal") != null ? raw(voidEl("c:max", { val: opts.valAxisMaxVal })) : null,
|
|
3634
|
+
logAxisBound(opts, "valAxisMinVal") != null ? raw(voidEl("c:min", { val: opts.valAxisMinVal })) : null
|
|
3630
3635
|
]);
|
|
3631
3636
|
const ticks = isScatterChart(opts._type) ? voidEl("c:majorTickMark", { val: "none" }) + voidEl("c:minorTickMark", { val: "none" }) + voidEl("c:tickLblPos", { val: "nextTo" }) : voidEl("c:majorTickMark", { val: opts.valAxisMajorTickMark || "out" }) + voidEl("c:minorTickMark", { val: opts.valAxisMinorTickMark || "none" }) + voidEl("c:tickLblPos", { val: opts.valAxisLabelPos || (opts.barDir === "col" ? "nextTo" : "low") });
|
|
3632
3637
|
const txPr = axisTextProps(axisLabelDefRPr({
|
|
@@ -3637,7 +3642,7 @@ function makeValAxis(opts, valAxisId) {
|
|
|
3637
3642
|
color: opts.valAxisLabelColor,
|
|
3638
3643
|
fontFace: opts.valAxisLabelFontFace
|
|
3639
3644
|
}), chartLang(opts), mapStated(opts.valAxisLabelRotate, (d) => convertAngleUnits(d, "valAxisLabelRotate")));
|
|
3640
|
-
const crosses = axisCrossing(opts.catAxisCrossesAt, axisPos === "r"
|
|
3645
|
+
const crosses = axisCrossing(opts.catAxisCrossesAt, axisPos === "r" ? "max" : "autoZero", "catAxisCrossesAt");
|
|
3641
3646
|
const crossBetween = opts.valAxisCrossBetween || (isScatterChart(opts._type) || !!(Array.isArray(opts._type) && opts._type.some((type) => asChartType(type.type) === "area")) ? "midCat" : "between");
|
|
3642
3647
|
return el("c:valAx", null, [
|
|
3643
3648
|
raw(voidEl("c:axId", { val: valAxisId })),
|
|
@@ -3715,8 +3720,7 @@ function makeSerAxis(opts, axisId, valAxisId) {
|
|
|
3715
3720
|
serLabelSkip !== void 0 ? raw(voidEl("c:tickLblSkip", { val: serLabelSkip })) : null
|
|
3716
3721
|
]);
|
|
3717
3722
|
}
|
|
3718
|
-
|
|
3719
|
-
//#region src/gen/chart/plot-cat-axis.ts
|
|
3723
|
+
// src/gen/chart/plot-cat-axis.ts
|
|
3720
3724
|
/**
|
|
3721
3725
|
* pptx-ts: Category-Axis Plot Assembly
|
|
3722
3726
|
*
|
|
@@ -3809,19 +3813,9 @@ const makeCatAxisPlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode
|
|
|
3809
3813
|
chartType === "bar3D" ? raw(voidEl("c:axId", { val: AXIS_ID_SERIES_PRIMARY })) : null
|
|
3810
3814
|
]);
|
|
3811
3815
|
};
|
|
3812
|
-
|
|
3813
|
-
//#region src/gen/chart/plot-scatter.ts
|
|
3816
|
+
// src/gen/chart/plot-scatter.ts
|
|
3814
3817
|
/**
|
|
3815
|
-
*
|
|
3816
|
-
*
|
|
3817
|
-
* Emits the `<c:scatterChart>` plot element. Scatter is the one family whose first data
|
|
3818
|
-
* row supplies X *values* rather than categories, so each `<c:ser>` carries an
|
|
3819
|
-
* `<c:xVal>`/`<c:yVal>` pair instead of `<c:cat>`/`<c:val>` -- which is why it does not
|
|
3820
|
-
* share the category-axis builder. Reached through {@link ./chart-xml}'s `makeChartType`
|
|
3821
|
-
* dispatch.
|
|
3822
|
-
*/
|
|
3823
|
-
/**
|
|
3824
|
-
* The `<c:spPr>` a scatter data label carries: no fill, no outline, no effects — the label is
|
|
3818
|
+
* The `<c:spPr>` a scatter data label carries: no fill, no outline, no effects. The label is
|
|
3825
3819
|
* text on the plot rather than a box. Both label builders in this file spelled it out.
|
|
3826
3820
|
*/
|
|
3827
3821
|
const TRANSPARENT_LABEL_SPPR = el("c:spPr", null, [
|
|
@@ -3835,7 +3829,7 @@ const TRANSPARENT_LABEL_SPPR = el("c:spPr", null, [
|
|
|
3835
3829
|
*
|
|
3836
3830
|
* Each `<a:fld>` id is minted per build. A field id has to be unique, which is a property a
|
|
3837
3831
|
* derived id would have to reproduce without an oracle for how far that uniqueness has to
|
|
3838
|
-
* reach
|
|
3832
|
+
* reach. So the ids stay random and the *comparison* gives: `NORMALIZERS` in
|
|
3839
3833
|
* `scripts/pptx-parts.mjs` erases exactly these two field types before the byte-identity gate
|
|
3840
3834
|
* diffs a part. Do not "fix" the nondeterminism here.
|
|
3841
3835
|
*/
|
|
@@ -3919,7 +3913,6 @@ function scatterSerShapeProps(opts, serColor, serIndex, lineSize) {
|
|
|
3919
3913
|
* Plot an XY scatter chart into `<c:scatterChart>` (paired X/Y numeric series).
|
|
3920
3914
|
*/
|
|
3921
3915
|
const makeScatterPlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode, sheet) => {
|
|
3922
|
-
const scatterVaryColors = data.length === 1 && opts.chartColors !== BARCHART_COLORS ? opts.chartColors || BARCHART_COLORS : null;
|
|
3923
3916
|
const sers = data.slice(1).map((obj) => {
|
|
3924
3917
|
const { idx, over, color: serColor, xVal, yVal } = xySeriesRefs(chartType, obj, data, opts, sheet, valFmtCode);
|
|
3925
3918
|
let labels = "";
|
|
@@ -3935,7 +3928,7 @@ const makeScatterPlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode
|
|
|
3935
3928
|
raw(seriesNameRef(obj, sheet)),
|
|
3936
3929
|
raw(scatterSerShapeProps(opts, serColor, idx, over?.lineSize)),
|
|
3937
3930
|
raw(serMarker(opts, serColor, serColor)),
|
|
3938
|
-
raw(makeSeriesDataPointsXml(chartType, obj, opts,
|
|
3931
|
+
raw(makeSeriesDataPointsXml(chartType, obj, opts, null)),
|
|
3939
3932
|
raw(labels),
|
|
3940
3933
|
raw(makeChartErrorBarsXml(chartType, obj.errorBars, obj)),
|
|
3941
3934
|
raw(xVal + yVal),
|
|
@@ -3951,15 +3944,14 @@ const makeScatterPlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode
|
|
|
3951
3944
|
raw(voidEl("c:axId", { val: valAxisId }))
|
|
3952
3945
|
]);
|
|
3953
3946
|
};
|
|
3954
|
-
|
|
3955
|
-
//#region src/gen/chart/plot-bubble.ts
|
|
3947
|
+
// src/gen/chart/plot-bubble.ts
|
|
3956
3948
|
/**
|
|
3957
3949
|
* Fill + outline + shadow for one bubble series, from the palette colour and the line options.
|
|
3958
3950
|
*
|
|
3959
3951
|
* Both the stroke fill and the cap read the same way as in `plot-scatter.ts` and
|
|
3960
3952
|
* `plot-cat-axis.ts`, which this used to differ from on both counts with nothing saying why.
|
|
3961
3953
|
* The colour went through `genXmlColorSelection` directly, so a `'transparent'` palette entry
|
|
3962
|
-
* reached colour validation, warned, and painted the bubble outline black
|
|
3954
|
+
* reached colour validation, warned, and painted the bubble outline black: the exact hole
|
|
3963
3955
|
* `chartColorLineFill` exists to close. The cap was hardcoded `flat`, so `lineCap` was accepted
|
|
3964
3956
|
* and silently dropped for bubble charts alone; it is visible here, because a bubble outline
|
|
3965
3957
|
* carries `lineDash` and a cap shapes the end of every dash.
|
|
@@ -4012,8 +4004,7 @@ const makeBubblePlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode,
|
|
|
4012
4004
|
raw(voidEl("c:axId", { val: valAxisId }))
|
|
4013
4005
|
]);
|
|
4014
4006
|
};
|
|
4015
|
-
|
|
4016
|
-
//#region src/gen/chart/plot-pie.ts
|
|
4007
|
+
// src/gen/chart/plot-pie.ts
|
|
4017
4008
|
/** One `<c:dPt>`: the slice's own fill, its border override, and the shared shadow. */
|
|
4018
4009
|
function pieDataPoint(idx, ptStyle, opts, fallbackColor) {
|
|
4019
4010
|
const border = ptStyle?.border ? createChartBorderLine(ptStyle.border) : opts.dataBorder ? createDataBorderLine(opts.dataBorder, "flat") : "";
|
|
@@ -4093,8 +4084,8 @@ function pieCategories(labels, sheet) {
|
|
|
4093
4084
|
* (`SeriesCollection(1).Values` reads `Empty` at that index in both), and export to a
|
|
4094
4085
|
* byte-identical PNG. A sensitivity check confirms the cache is what paints: perturbing a
|
|
4095
4086
|
* *neighbouring* cached value moves both the read-back and the pixels.
|
|
4096
|
-
* - `<c:v>Infinity</c:v>` was not. PowerPoint refuses the package with 0x80070570
|
|
4097
|
-
* corrupt-file error
|
|
4087
|
+
* - `<c:v>Infinity</c:v>` was not. PowerPoint refuses the package with 0x80070570 (the
|
|
4088
|
+
* corrupt-file error), and so does `NaN` or `INF` in that position. A pie was therefore the one
|
|
4098
4089
|
* family where a non-finite value reached the deck instead of being warned about and dropped.
|
|
4099
4090
|
*/
|
|
4100
4091
|
function pieValues(obj, count, valFmtCode, sheet) {
|
|
@@ -4156,8 +4147,7 @@ function makePiePlot(chartType, data, opts, valFmtCode, sheet) {
|
|
|
4156
4147
|
chartType === "doughnut" ? raw(voidEl("c:holeSize", { val: opts.holeSize ?? 50 })) : null
|
|
4157
4148
|
]);
|
|
4158
4149
|
}
|
|
4159
|
-
|
|
4160
|
-
//#region src/gen/chart/plot-stock.ts
|
|
4150
|
+
// src/gen/chart/plot-stock.ts
|
|
4161
4151
|
/**
|
|
4162
4152
|
* pptx-ts: Stock (High-Low-Close) Plot Assembly
|
|
4163
4153
|
*
|
|
@@ -4215,7 +4205,7 @@ const makeStockPlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode,
|
|
|
4215
4205
|
raw(voidEl("c:idx", { val: volumeIdx })),
|
|
4216
4206
|
raw(voidEl("c:order", { val: volumeIdx })),
|
|
4217
4207
|
raw(seriesNameRef(volumeSeries, sheet)),
|
|
4218
|
-
raw(el("c:spPr", null, raw(genXmlColorSelection(namedColorOr(opts.seriesOptions?.[volumeIdx]?.color, chartColors
|
|
4208
|
+
raw(el("c:spPr", null, raw(genXmlColorSelection(namedColorOr(opts.seriesOptions?.[volumeIdx]?.color, paletteColor(chartColors, 0), "seriesOptions color"))))),
|
|
4219
4209
|
raw(voidEl("c:invertIfNegative", { val: 0 })),
|
|
4220
4210
|
raw(catValRefs(volumeSeries, opts, valFmtCode, sheet, { multiLevel: false }))
|
|
4221
4211
|
]);
|
|
@@ -4232,7 +4222,7 @@ const makeStockPlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode,
|
|
|
4232
4222
|
}
|
|
4233
4223
|
const sers = stockSeries.map((obj, pos) => {
|
|
4234
4224
|
const idx = seriesIdx(obj, chartType);
|
|
4235
|
-
return makeStockLineSer(idx, obj, opts, valFmtCode, !spec.upDownBars && pos === stockSeries.length - 1 ? namedColorOr(opts.seriesOptions?.[idx]?.color, paletteColor(chartColors, idx
|
|
4225
|
+
return makeStockLineSer(idx, obj, opts, valFmtCode, !spec.upDownBars && pos === stockSeries.length - 1 ? namedColorOr(opts.seriesOptions?.[idx]?.color, paletteColor(chartColors, idx), "seriesOptions color") : null, sheet);
|
|
4236
4226
|
}).join("");
|
|
4237
4227
|
const hiLowLines = el("c:hiLowLines", null, raw(el("c:spPr", null, [raw(dimmedTextLine(75e3, 25e3)), raw(voidEl("a:effectLst"))])));
|
|
4238
4228
|
const upDownBars = spec.upDownBars ? el("c:upDownBars", null, [
|
|
@@ -4260,15 +4250,14 @@ const makeStockPlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode,
|
|
|
4260
4250
|
]);
|
|
4261
4251
|
return strXml;
|
|
4262
4252
|
};
|
|
4263
|
-
|
|
4264
|
-
//#region src/gen/chart/plot-surface.ts
|
|
4253
|
+
// src/gen/chart/plot-surface.ts
|
|
4265
4254
|
/**
|
|
4266
4255
|
* pptx-ts: Surface Plot Assembly
|
|
4267
4256
|
*
|
|
4268
4257
|
* Emits the classic `<c:surface3DChart>` (a 3-D surface) or `<c:surfaceChart>` (a 2-D
|
|
4269
4258
|
* contour / top view), selected by the `surface3D` option; `wireframe` toggles the
|
|
4270
4259
|
* mesh-only look. A surface chart interpolates a colored sheet over the category (X) and
|
|
4271
|
-
* series (Z) axes with the value as height (Y), so
|
|
4260
|
+
* series (Z) axes with the value as height (Y), so, like `bar3D`, it needs all three
|
|
4272
4261
|
* axes and a `<c:view3D>` + floor/side/back walls (emitted by the surface branch of
|
|
4273
4262
|
* `makeChartHeaderXml`). Reached through {@link ./chart-xml}'s `makeChartType` dispatch.
|
|
4274
4263
|
*/
|
|
@@ -4299,7 +4288,7 @@ function makeSurfaceSer(chartType, obj, opts, valFmtCode, seriesColor, sheet) {
|
|
|
4299
4288
|
const makeSurfacePlot = (chartType, data, opts, valAxisId, catAxisId, valFmtCode, sheet) => {
|
|
4300
4289
|
const tag = isSurface3D(opts) ? "surface3DChart" : "surfaceChart";
|
|
4301
4290
|
const chartColors = resolveChartPalette(opts);
|
|
4302
|
-
const sers = data.map((obj, idx) => makeSurfaceSer(chartType, obj, opts, valFmtCode, paletteColor(chartColors, idx
|
|
4291
|
+
const sers = data.map((obj, idx) => makeSurfaceSer(chartType, obj, opts, valFmtCode, paletteColor(chartColors, idx), sheet)).join("");
|
|
4303
4292
|
return el(`c:${tag}`, null, [
|
|
4304
4293
|
raw(voidEl("c:wireframe", { val: xsdBool(opts.surfaceWireframe) })),
|
|
4305
4294
|
raw(sers),
|
|
@@ -4333,8 +4322,7 @@ function makeSurfaceScene(opts) {
|
|
|
4333
4322
|
];
|
|
4334
4323
|
return el("c:view3D", null, scene) + el("c:floor", null, raw(wall)) + el("c:sideWall", null, raw(wall)) + el("c:backWall", null, raw(wall));
|
|
4335
4324
|
}
|
|
4336
|
-
|
|
4337
|
-
//#region src/gen/chart/chart-xml.ts
|
|
4325
|
+
// src/gen/chart/chart-xml.ts
|
|
4338
4326
|
/**
|
|
4339
4327
|
* pptx-ts: Chart DrawingML Assembly
|
|
4340
4328
|
*
|
|
@@ -4359,8 +4347,8 @@ const CHART_SPACE_NS = {
|
|
|
4359
4347
|
/**
|
|
4360
4348
|
* Whether a chart-area/plot-area `fill` says anything the fill dispatch can act on.
|
|
4361
4349
|
*
|
|
4362
|
-
* `c:spPr` is `a:CT_ShapeProperties
|
|
4363
|
-
* shape path writes into
|
|
4350
|
+
* `c:spPr` is `a:CT_ShapeProperties`, the same optional `EG_FillProperties` group the
|
|
4351
|
+
* shape path writes into, so gradient, pattern and an omitted fill child are all legal
|
|
4364
4352
|
* here. The gate used to be `fill?.color`, which meant every spelling carrying no colour
|
|
4365
4353
|
* (`gradient`, `pattern`, `image`, `inherit`) fell to the no-fill arm and did nothing.
|
|
4366
4354
|
*
|
|
@@ -4374,7 +4362,7 @@ const CHART_SPACE_NS = {
|
|
|
4374
4362
|
* matches the shape path: only `line` infers its type from a bare `gradient`, fills have
|
|
4375
4363
|
* always wanted `type: 'gradient'` spelled out.
|
|
4376
4364
|
*
|
|
4377
|
-
* A bare {@link Color} string is stated
|
|
4365
|
+
* A bare {@link Color} string is stated: it is the solid-colour shorthand every other fill
|
|
4378
4366
|
* site takes. This one used to be the exception: the string reached here having already been
|
|
4379
4367
|
* spread into `{0:'F',1:'F',…}` by `copyChartOptions`, so it named neither `color` nor `type`
|
|
4380
4368
|
* and a chart area asked for `fill: 'FF0000'` came out `<a:noFill/>`.
|
|
@@ -4389,7 +4377,7 @@ function isStatedFill(fill) {
|
|
|
4389
4377
|
* The override bag carries a third state the rest of the generator does not: a *present*
|
|
4390
4378
|
* `undefined`, meaning "this subchart's own value was rejected, so emit nothing here", as against
|
|
4391
4379
|
* an absent key, which inherits the chart-level value (see {@link ChartOptsOverrides}). The spread
|
|
4392
|
-
* is what applies that distinction
|
|
4380
|
+
* is what applies that distinction, and once it has, the keys still holding `undefined` have said
|
|
4393
4381
|
* everything they had to say, so they are dropped. What the plot builders receive is an ordinary
|
|
4394
4382
|
* options bag with one spelling of absent.
|
|
4395
4383
|
* @param chartOptions - the chart-level options, already normalized
|
|
@@ -4419,7 +4407,7 @@ function makeChartHeaderXml(rel) {
|
|
|
4419
4407
|
titleUnderline: rel.opts.titleUnderline,
|
|
4420
4408
|
titlePos: rel.opts.titlePos,
|
|
4421
4409
|
titleRotate: rel.opts.titleRotate
|
|
4422
|
-
}, rel.opts.x, rel.opts.y) + voidEl("c:autoTitleDeleted", { val: 0 }) : voidEl("c:autoTitleDeleted", { val: 1 });
|
|
4410
|
+
}, rel.opts.x ?? void 0, rel.opts.y ?? void 0) + voidEl("c:autoTitleDeleted", { val: 0 }) : voidEl("c:autoTitleDeleted", { val: 1 });
|
|
4423
4411
|
if (rel.opts._type === "bar3D") return title + el("c:view3D", null, [
|
|
4424
4412
|
raw(voidEl("c:rotX", { val: rel.opts.v3DRotX })),
|
|
4425
4413
|
raw(voidEl("c:rotY", { val: rel.opts.v3DRotY })),
|
|
@@ -4532,26 +4520,31 @@ function makeChartAxesXml(rel, plan) {
|
|
|
4532
4520
|
const valOverride = (idx) => rel.opts.valAxes?.[idx];
|
|
4533
4521
|
const overrideCount = rel.opts.valAxes?.length ?? 0;
|
|
4534
4522
|
if (overrideCount > 2) warn("chart/option-not-supported", `"valAxes" and "catAxes" have ${overrideCount} entries, but a chart has one primary and one secondary axis of each kind; the entries past the second are ignored.`);
|
|
4523
|
+
const crossing = (key, entry) => entry?.[key] === void 0 ? {} : { [key]: entry[key] };
|
|
4535
4524
|
strXml += makeCatAxis({
|
|
4536
4525
|
...rel.opts,
|
|
4537
4526
|
...catOverride(0),
|
|
4527
|
+
...crossing("valAxisCrossesAt", valOverride(0)),
|
|
4538
4528
|
...comboCatAxisType(false)
|
|
4539
4529
|
}, AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_VALUE_PRIMARY);
|
|
4540
4530
|
strXml += makeValAxis({
|
|
4541
4531
|
...rel.opts,
|
|
4542
|
-
...valOverride(0)
|
|
4532
|
+
...valOverride(0),
|
|
4533
|
+
...crossing("catAxisCrossesAt", catOverride(0))
|
|
4543
4534
|
}, AXIS_ID_VALUE_PRIMARY);
|
|
4544
4535
|
if (rel.opts._type === "bar3D" || rel.opts._type === "surface") strXml += makeSerAxis(rel.opts, AXIS_ID_SERIES_PRIMARY, AXIS_ID_VALUE_PRIMARY);
|
|
4545
4536
|
if (plan.secondary) {
|
|
4546
4537
|
strXml += makeValAxis({
|
|
4547
4538
|
...rel.opts,
|
|
4548
4539
|
...plan.secondaryVal ? {} : { valAxisHidden: true },
|
|
4549
|
-
...valOverride(1)
|
|
4540
|
+
...valOverride(1),
|
|
4541
|
+
...crossing("catAxisCrossesAt", catOverride(1))
|
|
4550
4542
|
}, AXIS_ID_VALUE_SECONDARY);
|
|
4551
4543
|
strXml += makeCatAxis({
|
|
4552
4544
|
...rel.opts,
|
|
4553
4545
|
...plan.secondaryCat ? {} : { catAxisHidden: true },
|
|
4554
4546
|
...catOverride(1),
|
|
4547
|
+
...crossing("valAxisCrossesAt", valOverride(1)),
|
|
4555
4548
|
...comboCatAxisType(true)
|
|
4556
4549
|
}, AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_VALUE_SECONDARY);
|
|
4557
4550
|
}
|
|
@@ -4564,7 +4557,7 @@ function makeChartAxesXml(rel, plan) {
|
|
|
4564
4557
|
*
|
|
4565
4558
|
* The lightest of the four `BorderProps` strokes: paint only, with neither the `a:prstDash`
|
|
4566
4559
|
* nor the `a:round` its siblings write. It also branches on the border being *absent* rather
|
|
4567
|
-
* than on `type: 'none'
|
|
4560
|
+
* than on `type: 'none'`: the caller here has an optional border where
|
|
4568
4561
|
* `createChartBorderLine` (`gen/chart/chart-parts.ts`) has a resolved one.
|
|
4569
4562
|
*/
|
|
4570
4563
|
function chartShapeProps(fill, border) {
|
|
@@ -4680,7 +4673,7 @@ function makeLegendXml(rel) {
|
|
|
4680
4673
|
for (const type of legendOrder(rel.opts, rel.opts._type)) {
|
|
4681
4674
|
const seriesCount = isXyChart(asChartType(type.type)) ? Math.max(0, type.data.length - 1) : type.data.length;
|
|
4682
4675
|
for (let i = 0; i < seriesCount; i++, position++) {
|
|
4683
|
-
if (type.options
|
|
4676
|
+
if (type.options.showLegend !== false) continue;
|
|
4684
4677
|
entries += el("c:legendEntry", null, [raw(voidEl("c:idx", { val: position })), raw(voidEl("c:delete", { val: 1 }))]);
|
|
4685
4678
|
}
|
|
4686
4679
|
}
|
|
@@ -4733,9 +4726,10 @@ function makeXmlCharts(rel) {
|
|
|
4733
4726
|
const secondary = plotsOnSecondaryAxes(options);
|
|
4734
4727
|
const valAxisId = secondary ? AXIS_ID_VALUE_SECONDARY : AXIS_ID_VALUE_PRIMARY;
|
|
4735
4728
|
const catAxisId = secondary ? AXIS_ID_CATEGORY_SECONDARY : AXIS_ID_CATEGORY_PRIMARY;
|
|
4736
|
-
|
|
4729
|
+
const plotOptions = withAxisValueFormat(options, rel.opts.valAxes?.[secondary ? 1 : 0], type.options.valLabelFormatCode);
|
|
4730
|
+
plots += makeChartType(asChartType(type.type), type.data, plotOptions, valAxisId, catAxisId, sheet);
|
|
4737
4731
|
}
|
|
4738
|
-
else if (rel.opts._type) plots = makeChartType(rel.opts._type, rel.data, rel.opts, AXIS_ID_VALUE_PRIMARY, AXIS_ID_CATEGORY_PRIMARY, sheet);
|
|
4732
|
+
else if (rel.opts._type) plots = makeChartType(rel.opts._type, rel.data, withAxisValueFormat(rel.opts, rel.opts.valAxes?.[0], void 0), AXIS_ID_VALUE_PRIMARY, AXIS_ID_CATEGORY_PRIMARY, sheet);
|
|
4739
4733
|
const axes = makeChartAxesXml(rel, plan);
|
|
4740
4734
|
const plotArea = el("c:plotArea", null, [
|
|
4741
4735
|
raw(makePlotAreaLayoutXml(rel)),
|
|
@@ -4762,14 +4756,6 @@ function makeXmlCharts(rel) {
|
|
|
4762
4756
|
]);
|
|
4763
4757
|
}
|
|
4764
4758
|
/**
|
|
4765
|
-
* Stable pptx-ts vendor GUID identifying the chart-metadata extension on `c:chartSpace/c:extLst`.
|
|
4766
|
-
* Custom data rides under this URI in a foreign namespace so PowerPoint preserves it (the extLst
|
|
4767
|
-
* mechanism) instead of stripping/repairing it as it would an unrecognised sibling element.
|
|
4768
|
-
*/
|
|
4769
|
-
const CHART_METADATA_EXT_URI = "{094A432E-1F6C-499B-95B8-B57DC9536949}";
|
|
4770
|
-
/** Foreign namespace for the chart-metadata extension payload. */
|
|
4771
|
-
const CHART_METADATA_NS = "http://ts-pptx.com/schema/chart/metadata";
|
|
4772
|
-
/**
|
|
4773
4759
|
* Create the chart-space extension-list XML carrying custom `metadata` key/value annotations.
|
|
4774
4760
|
* Emits nothing when metadata is absent or contains no valid entries. Keys must be non-empty
|
|
4775
4761
|
* strings and values must be strings; invalid entries are dropped with a warning rather than
|
|
@@ -4785,7 +4771,7 @@ function genXmlChartMetadata(metadata) {
|
|
|
4785
4771
|
}
|
|
4786
4772
|
let items = "";
|
|
4787
4773
|
for (const [key, value] of Object.entries(metadata)) {
|
|
4788
|
-
if (
|
|
4774
|
+
if (key.length === 0) {
|
|
4789
4775
|
warn("chart/invalid-metadata-key", `chart metadata key "${String(key)}" is not a non-empty string; entry skipped.`);
|
|
4790
4776
|
continue;
|
|
4791
4777
|
}
|
|
@@ -4802,6 +4788,22 @@ function genXmlChartMetadata(metadata) {
|
|
|
4802
4788
|
return el("c:extLst", null, raw(el("c:ext", { uri: CHART_METADATA_EXT_URI }, raw(el("pgm:metadata", { "xmlns:pgm": CHART_METADATA_NS }, raw(items))))));
|
|
4803
4789
|
}
|
|
4804
4790
|
/**
|
|
4791
|
+
* A plot's options with the value format its series caches take: a subchart's own
|
|
4792
|
+
* `valLabelFormatCode`, else the one stated on the `valAxes` entry for the axis it plots on, else
|
|
4793
|
+
* the chart's. The entry's format was spread over that axis' builder only, which never reads it, so
|
|
4794
|
+
* the caches kept the chart's (#142).
|
|
4795
|
+
* @param opts - the plot's resolved options
|
|
4796
|
+
* @param axis - the `valAxes` entry for the value axis the plot is on
|
|
4797
|
+
* @param own - the format the subchart states itself
|
|
4798
|
+
*/
|
|
4799
|
+
function withAxisValueFormat(opts, axis, own) {
|
|
4800
|
+
const format = own ?? axis?.valLabelFormatCode;
|
|
4801
|
+
return format === void 0 ? opts : {
|
|
4802
|
+
...opts,
|
|
4803
|
+
valLabelFormatCode: format
|
|
4804
|
+
};
|
|
4805
|
+
}
|
|
4806
|
+
/**
|
|
4805
4807
|
* Create XML string for any given chart type.
|
|
4806
4808
|
* Dispatches to a per-family plot helper; resolves the effective value number format first.
|
|
4807
4809
|
* @param {ChartType} chartType chart type name
|
|
@@ -4828,11 +4830,10 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId, sheet) {
|
|
|
4828
4830
|
case "surface": return makeSurfacePlot(chartType, data, opts, valAxisId, catAxisId, valFmtCode, sheet);
|
|
4829
4831
|
case "doughnut":
|
|
4830
4832
|
case "pie": return makePiePlot(chartType, data, opts, valFmtCode, sheet);
|
|
4831
|
-
default: throw new InternalError("chart/type-not-routed", `makeChartType: "${String(chartType)}" has no <c:...Chart> plot
|
|
4833
|
+
default: throw new InternalError("chart/type-not-routed", `makeChartType: "${String(chartType)}" has no <c:...Chart> plot: the chartEx catalog is built by makeXmlChartEx, and a newly added classic type needs an arm here`, { detail: { chartType } });
|
|
4832
4834
|
}
|
|
4833
4835
|
}
|
|
4834
|
-
|
|
4835
|
-
//#region src/gen/chart/chartex-data.ts
|
|
4836
|
+
// src/gen/chart/chartex-data.ts
|
|
4836
4837
|
/**
|
|
4837
4838
|
* The numeric-dimension tag PowerPoint expects varies by layout. The flat layouts (waterfall,
|
|
4838
4839
|
* funnel, histogram, pareto, boxWhisker) use `type="val"`; the hierarchical treemap/sunburst use
|
|
@@ -4852,7 +4853,7 @@ function valueDimType(type) {
|
|
|
4852
4853
|
* `<cx:externalData r:id="rId1">` points at the embedded workbook (same `rId1` the chart part's
|
|
4853
4854
|
* `.rels` maps to the `.xlsx`).
|
|
4854
4855
|
*
|
|
4855
|
-
* Category labels are `string[][]
|
|
4856
|
+
* Category labels are `string[][]`: one inner array per hierarchy level (leaf first). A flat chart
|
|
4856
4857
|
* has a single level; treemap/sunburst carry several. Each level becomes one `<cx:lvl>`, emitted
|
|
4857
4858
|
* leaf-first to match PowerPoint. The workbook ({@link ./embed-xlsx}) lays the levels out in
|
|
4858
4859
|
* columns A..N (outermost in A, leaf in the last label column) with the value series in the next
|
|
@@ -4901,7 +4902,7 @@ function makeChartExData(rel, sheet) {
|
|
|
4901
4902
|
return el("cx:chartData", null, [raw(externalData), raw(data)]);
|
|
4902
4903
|
}
|
|
4903
4904
|
/**
|
|
4904
|
-
* The `Sheet1` cell holding the series name (the numeric dimension's header)
|
|
4905
|
+
* The `Sheet1` cell holding the series name (the numeric dimension's header): the column immediately
|
|
4905
4906
|
* after all label columns, row 1. A category-less histogram lands on `$A$1`; a flat chart on
|
|
4906
4907
|
* `$B$1`; a 3-level treemap on `$D$1`.
|
|
4907
4908
|
* @param {WorksheetLayout} sheet - the chart's worksheet layout
|
|
@@ -4910,12 +4911,11 @@ function makeChartExData(rel, sheet) {
|
|
|
4910
4911
|
function chartExSeriesNameRef(sheet) {
|
|
4911
4912
|
return sheetCellRef(sheet.valueColumn(0), 1);
|
|
4912
4913
|
}
|
|
4913
|
-
|
|
4914
|
-
//#region src/gen/chart/chartex-xml.ts
|
|
4914
|
+
// src/gen/chart/chartex-xml.ts
|
|
4915
4915
|
/**
|
|
4916
4916
|
* pptx-ts: chartEx (`cx:`) Chart Assembly
|
|
4917
4917
|
*
|
|
4918
|
-
* Builds a chartEx chart part `ppt/charts/chartEx{N}.xml
|
|
4918
|
+
* Builds a chartEx chart part `ppt/charts/chartEx{N}.xml`: the `<cx:chartSpace>` for the
|
|
4919
4919
|
* Office-2016 chart family (currently `waterfall`, `funnel`, `treemap`, `sunburst`, `histogram`,
|
|
4920
4920
|
* `pareto`, `boxWhisker`, `regionMap`).
|
|
4921
4921
|
* This is the chartEx analogue of
|
|
@@ -4932,7 +4932,7 @@ function chartExSeriesNameRef(sheet) {
|
|
|
4932
4932
|
*/
|
|
4933
4933
|
/**
|
|
4934
4934
|
* Map a chartEx {@link ChartType} to its `<cx:series layoutId>` token (the CT_SeriesLayout value
|
|
4935
|
-
* PowerPoint keys the chart geometry on). Throws on anything it does not own
|
|
4935
|
+
* PowerPoint keys the chart geometry on). Throws on anything it does not own; see the `default`
|
|
4936
4936
|
* arm for which members those are and why reaching it is a routing bug.
|
|
4937
4937
|
*/
|
|
4938
4938
|
function chartExLayoutId(type) {
|
|
@@ -4944,13 +4944,13 @@ function chartExLayoutId(type) {
|
|
|
4944
4944
|
case "histogram": return "clusteredColumn";
|
|
4945
4945
|
case "boxWhisker": return "boxWhisker";
|
|
4946
4946
|
case "regionMap": return "regionMap";
|
|
4947
|
-
default: throw new InternalError("chart/type-not-routed", `chartExLayoutId: "${String(type)}" has no <cx:series> layoutId
|
|
4947
|
+
default: throw new InternalError("chart/type-not-routed", `chartExLayoutId: "${String(type)}" has no <cx:series> layoutId: classic chart types belong to makeXmlCharts, pareto is built by makeParetoSeries, and a newly added chartEx type needs an arm here`, { detail: { chartType: type } });
|
|
4948
4948
|
}
|
|
4949
4949
|
}
|
|
4950
4950
|
/**
|
|
4951
4951
|
* A deterministic `uniqueId` GUID for a `<cx:series>`, derived from the chart's package-global id.
|
|
4952
4952
|
* PowerPoint stamps a random GUID here; deriving it keeps output byte-stable (the project pins
|
|
4953
|
-
* chart determinism
|
|
4953
|
+
* chart determinism; the package-wide id this derives from is assigned at write time in
|
|
4954
4954
|
* `package/assemble.ts`, STEP 2). `seriesIdx`
|
|
4955
4955
|
* distinguishes multiple series within one chart (pareto emits two), varying the 4th GUID group so
|
|
4956
4956
|
* every series still gets a distinct id.
|
|
@@ -4965,10 +4965,10 @@ function chartExLegendPos(pos) {
|
|
|
4965
4965
|
/**
|
|
4966
4966
|
* The `<cx:axisId>` binding on a `<cx:series>` (which value/category axis the series plots against).
|
|
4967
4967
|
*
|
|
4968
|
-
* NOTE
|
|
4968
|
+
* NOTE: a schema-vs-PowerPoint divergence (the exact mirror of the histogram `binCount` gotcha):
|
|
4969
4969
|
* the OpenXML SDK models `cx:axisId` as an `OpenXmlLeafTextElement`, so the OOXML validator only
|
|
4970
4970
|
* accepts the text-content form `<cx:axisId>1</cx:axisId>` and flags the `val` attribute as
|
|
4971
|
-
* undeclared. But PowerPoint desktop REFUSES to open a deck using the text form (0x80070570)
|
|
4971
|
+
* undeclared. But PowerPoint desktop REFUSES to open a deck using the text form (0x80070570). It
|
|
4972
4972
|
* writes and requires the ATTRIBUTE form `<cx:axisId val="1"/>` (matching the classic `c:axId`).
|
|
4973
4973
|
* PowerPoint is the authoritative oracle here, so the attribute form is emitted; the resulting
|
|
4974
4974
|
* validator complaint on `cx:axisId/@val` is expected and whitelisted in the schema-case test.
|
|
@@ -4978,20 +4978,20 @@ function makeChartExAxisId(id) {
|
|
|
4978
4978
|
}
|
|
4979
4979
|
/**
|
|
4980
4980
|
* Build the histogram `<cx:binning>` element from the caller's `binning` opt. PowerPoint bins the
|
|
4981
|
-
* raw observations automatically; the only control wired here is `intervalClosed
|
|
4981
|
+
* raw observations automatically; the only control wired here is `intervalClosed`: whether each
|
|
4982
4982
|
* bin interval is right-closed (`"r"`, PowerPoint's default) or left-closed (`"l"`).
|
|
4983
4983
|
*
|
|
4984
4984
|
* NOTE: explicit bin geometry (`binCount`/`binSize` child elements, `underflow`/`overflow`
|
|
4985
4985
|
* attributes) is intentionally NOT emitted. Although `<cx:binCount>`/`<cx:binSize>` pass OOXML
|
|
4986
4986
|
* schema validation (they are declared children of `cx:binning` in the OpenXML SDK), PowerPoint
|
|
4987
|
-
* desktop refuses to open a deck that contains them (0x80004005)
|
|
4987
|
+
* desktop refuses to open a deck that contains them (0x80004005), so shipping them would corrupt
|
|
4988
4988
|
* the file. They stay deferred until their real requirements are pinned down against PowerPoint.
|
|
4989
4989
|
*/
|
|
4990
4990
|
function makeChartExBinning(binning) {
|
|
4991
4991
|
return voidEl("cx:binning", { intervalClosed: binning?.intervalClosed === "l" ? "l" : "r" });
|
|
4992
4992
|
}
|
|
4993
4993
|
/**
|
|
4994
|
-
* Build the box-and-whisker `<cx:layoutPr>` body
|
|
4994
|
+
* Build the box-and-whisker `<cx:layoutPr>` body: a `<cx:visibility>` toggle set plus a
|
|
4995
4995
|
* `<cx:statistics>` quartile-method choice, in that document order (what PowerPoint itself emits).
|
|
4996
4996
|
* All flags default to PowerPoint's own defaults: exclusive quartiles, mean marker on, outlier
|
|
4997
4997
|
* points on, the mean-line and the full non-outlier scatter off. Booleans map to the `0`/`1`
|
|
@@ -5009,16 +5009,16 @@ function makeBoxWhiskerLayoutPr(stats) {
|
|
|
5009
5009
|
return el("cx:layoutPr", null, [raw(visibility), raw(statistics)]);
|
|
5010
5010
|
}
|
|
5011
5011
|
/**
|
|
5012
|
-
* Build the region-map `<cx:layoutPr>` body
|
|
5012
|
+
* Build the region-map `<cx:layoutPr>` body: a single `<cx:geography>` hint telling PowerPoint how
|
|
5013
5013
|
* to interpret the category labels as geographic region names. `cultureLanguage`/`cultureRegion`
|
|
5014
5014
|
* (both schema-REQUIRED) resolve ambiguous names (e.g. "Georgia" the country vs. the US state);
|
|
5015
5015
|
* `attribution` is Bing's fixed acknowledgement string.
|
|
5016
5016
|
*
|
|
5017
|
-
* NOTE
|
|
5017
|
+
* NOTE: PowerPoint itself also nests a `<cx:geoCache>` here holding a base64 binary blob: its
|
|
5018
5018
|
* cached Bing geometry for the resolved regions. That blob is produced by an online Bing lookup and
|
|
5019
5019
|
* cannot be reproduced offline, so it is intentionally OMITTED. PowerPoint re-resolves the geography
|
|
5020
5020
|
* from the region names when the deck is opened (verified over COM: the deck opens and reads back as
|
|
5021
|
-
* a regionMap either way)
|
|
5021
|
+
* a regionMap either way). This is why a region map is documented as best-effort/write-only and
|
|
5022
5022
|
* renders blank if the names don't match PowerPoint's geography database.
|
|
5023
5023
|
*/
|
|
5024
5024
|
function makeGeographyLayoutPr(geo) {
|
|
@@ -5045,7 +5045,7 @@ function makeChartExDataLabels(rel) {
|
|
|
5045
5045
|
}))) : "";
|
|
5046
5046
|
}
|
|
5047
5047
|
/**
|
|
5048
|
-
* Build the pareto `<cx:series>` PAIR
|
|
5048
|
+
* Build the pareto `<cx:series>` PAIR; pareto is the first chartEx layout that emits more than one
|
|
5049
5049
|
* series. Series 0 is a `clusteredColumn` bound to value axis 1 whose `<cx:aggregation/>` tells
|
|
5050
5050
|
* PowerPoint to sum the values per category, sort the bars descending, and drive the cumulative
|
|
5051
5051
|
* line. Series 1 is the `paretoLine` itself: it carries `ownerIdx="0"` (it derives its data from
|
|
@@ -5073,7 +5073,7 @@ function makeChartExSeries(rel, sheet) {
|
|
|
5073
5073
|
const type = opts._type;
|
|
5074
5074
|
if (type === "pareto") return makeParetoSeries(rel, sheet);
|
|
5075
5075
|
let layoutPr = "";
|
|
5076
|
-
if (type === "waterfall" &&
|
|
5076
|
+
if (type === "waterfall" && opts.subtotals) {
|
|
5077
5077
|
const idxs = opts.subtotals.map((idx) => voidEl("cx:idx", { val: idx })).join("");
|
|
5078
5078
|
layoutPr = el("cx:layoutPr", null, raw(el("cx:subtotals", null, raw(idxs))));
|
|
5079
5079
|
} else if (type === "treemap") layoutPr = el("cx:layoutPr", null, raw(voidEl("cx:parentLabelLayout", { val: "overlapping" })));
|
|
@@ -5120,8 +5120,8 @@ const CHARTEX_CAT_GAP_WIDTH = {
|
|
|
5120
5120
|
/**
|
|
5121
5121
|
* Build the `<cx:axis>` list for a layout, matched to what PowerPoint itself emits for each.
|
|
5122
5122
|
*
|
|
5123
|
-
* Four of the five axis-bearing layouts are the same pair
|
|
5124
|
-
* gridlined value axis (id 1)
|
|
5123
|
+
* Four of the five axis-bearing layouts are the same pair, a category axis (id 0) and a
|
|
5124
|
+
* gridlined value axis (id 1), differing only in gap width, so they are a table rather than
|
|
5125
5125
|
* four arms. The two that are not: the **funnel** has a SINGLE category axis, which PowerPoint
|
|
5126
5126
|
* numbers id 1, with no value axis and no gridlines (its bars run horizontally off one
|
|
5127
5127
|
* category scale); and the **pareto** adds a third axis for its cumulative line.
|
|
@@ -5186,8 +5186,7 @@ function makeXmlChartEx(rel) {
|
|
|
5186
5186
|
"xmlns:r": OOXML_NS.r
|
|
5187
5187
|
}, [raw(makeChartExData(rel, sheet)), raw(chart)]);
|
|
5188
5188
|
}
|
|
5189
|
-
|
|
5190
|
-
//#region src/gen/chart/chartex-style.ts
|
|
5189
|
+
// src/gen/chart/chartex-style.ts
|
|
5191
5190
|
/**
|
|
5192
5191
|
* pptx-ts: chartEx (cx:) Style + Color Parts
|
|
5193
5192
|
*
|
|
@@ -5195,12 +5194,12 @@ function makeXmlChartEx(rel) {
|
|
|
5195
5194
|
* (`style{N}.xml`, `cs:chartStyle`) and a chart-color-style part (`colors{N}.xml`,
|
|
5196
5195
|
* `cs:colorStyle`), linked from the chartEx part's `.rels` via the MS `chartStyle` /
|
|
5197
5196
|
* `chartColorStyle` relationship types. This is NOT optional: PowerPoint reports a chartEx deck
|
|
5198
|
-
* that lacks them as corrupt (0x80070570)
|
|
5197
|
+
* that lacks them as corrupt (0x80070570), a failure the OOXML schema validator does not catch,
|
|
5199
5198
|
* found via the desktop COM smoke (`pnpm run test:com`).
|
|
5200
5199
|
*
|
|
5201
5200
|
* The two payloads below are PowerPoint's own generic, chart-type-agnostic defaults (the same
|
|
5202
5201
|
* boilerplate Office writes for any new chartEx chart), captured verbatim and shipped as a static
|
|
5203
|
-
* template
|
|
5202
|
+
* template, analogous to the default theme/worksheet boilerplate the library already embeds. They
|
|
5204
5203
|
* reference theme scheme colors, so they adapt to the deck theme without per-chart customization.
|
|
5205
5204
|
*/
|
|
5206
5205
|
/**
|
|
@@ -5221,18 +5220,17 @@ function makeChartExColorsXml() {
|
|
|
5221
5220
|
function makeChartExStyleXml() {
|
|
5222
5221
|
return XML_DECL + CHARTEX_STYLE_BODY;
|
|
5223
5222
|
}
|
|
5224
|
-
|
|
5225
|
-
//#region src/gen/chart/embed-xlsx.ts
|
|
5223
|
+
// src/gen/chart/embed-xlsx.ts
|
|
5226
5224
|
/**
|
|
5227
5225
|
* pptx-ts: Chart Embedded-Workbook Generation
|
|
5228
5226
|
*
|
|
5229
|
-
* Builds the embedded `.xlsx` workbook that backs a chart's cached data
|
|
5227
|
+
* Builds the embedded `.xlsx` workbook that backs a chart's cached data: the data
|
|
5230
5228
|
* source PowerPoint opens when a user edits the chart. `createExcelWorksheet` writes
|
|
5231
5229
|
* the workbook plus the chart part + its `.rels` into the presentation package;
|
|
5232
5230
|
* `buildEmbeddedWorksheet` and `chartPartBodies` are also used by slide extraction
|
|
5233
|
-
* (`
|
|
5231
|
+
* (`PptxTs.extractSlides`), whose chart relationships `appendSlides` rebuilds itself against the
|
|
5234
5232
|
* parts it reserves. Everything here is a pure string/bytes
|
|
5235
|
-
* builder
|
|
5233
|
+
* builder: no I/O beyond the passed-in ZipWriter, no mutation of the presentation model.
|
|
5236
5234
|
*
|
|
5237
5235
|
* The chart's `chart.xml` DrawingML lives in `./chart-xml.ts`; the series↔worksheet-cell
|
|
5238
5236
|
* mapping the two sides share lives in `./data-refs.ts`.
|
|
@@ -5262,10 +5260,10 @@ const XLSX_STYLES_XML = "<styleSheet xmlns=\"http://schemas.openxmlformats.org/s
|
|
|
5262
5260
|
const XLSX_THEME_XML = "<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>" + FMT_SCHEME_XML + "</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>";
|
|
5263
5261
|
/**
|
|
5264
5262
|
* Build the chart's embedded Excel workbook as a standalone OPC package and
|
|
5265
|
-
* return its bytes
|
|
5263
|
+
* return its bytes: the data source PowerPoint opens when a user edits the
|
|
5266
5264
|
* chart's data. Pure (no zip side effects), so both the package write path
|
|
5267
5265
|
* ({@link createExcelWorksheet}) and the read-side injection path
|
|
5268
|
-
* (`
|
|
5266
|
+
* (`PptxTs.extractSlides`) can reuse it.
|
|
5269
5267
|
* @param {SlideRelChart} chartObject - chart object
|
|
5270
5268
|
* @return {Uint8Array} the embedded `.xlsx` package bytes
|
|
5271
5269
|
*/
|
|
@@ -5324,13 +5322,7 @@ function buildEmbeddedWorksheet(chartObject) {
|
|
|
5324
5322
|
raw(el("HyperlinksChanged", null, "false")),
|
|
5325
5323
|
raw(el("AppVersion", null, "16.0300"))
|
|
5326
5324
|
]) + "\n");
|
|
5327
|
-
|
|
5328
|
-
zipExcel.add("docProps/core.xml", XML_DECL + el("cp:coreProperties", CORE_PROPS_NS, [
|
|
5329
|
-
raw(el("dc:creator", null, "TsPptx")),
|
|
5330
|
-
raw(el("cp:lastModifiedBy", null, "TsPptx")),
|
|
5331
|
-
raw(el("dcterms:created", { "xsi:type": "dcterms:W3CDTF" }, now)),
|
|
5332
|
-
raw(el("dcterms:modified", { "xsi:type": "dcterms:W3CDTF" }, now))
|
|
5333
|
-
]));
|
|
5325
|
+
zipExcel.add("docProps/core.xml", XML_DECL + el("cp:coreProperties", CORE_PROPS_NS, [raw(el("dc:creator", null, "pptx-ts")), raw(el("cp:lastModifiedBy", null, "pptx-ts"))]));
|
|
5334
5326
|
zipExcel.add("xl/_rels/workbook.xml.rels", XML_DECL + relationshipsEl([
|
|
5335
5327
|
relationshipEl("rId3", OFFICE_REL + "styles", "styles.xml"),
|
|
5336
5328
|
relationshipEl("rId2", THEME_REL, "theme/theme1.xml"),
|
|
@@ -5468,7 +5460,7 @@ function buildXlsxSheet(data, layout) {
|
|
|
5468
5460
|
* reached this sheet (`?? ''` at the call sites) and which Excel reads back as an empty cell.
|
|
5469
5461
|
* A **non-finite** number is the same thing: `<v>Infinity</v>` (or `NaN`, or `INF`) is not a
|
|
5470
5462
|
* number Excel will parse, and it refuses the whole workbook with 0x3EC rather than skipping
|
|
5471
|
-
* the cell
|
|
5463
|
+
* the cell. PowerPoint hides that failure, because it does not parse the embedding on open. It
|
|
5472
5464
|
* surfaces on "Edit Data", by which point the chart's own cache is already clean: `numCachePt`
|
|
5473
5465
|
* (`./chart-parts.ts`) and the chartEx numeric dimension (`./chartex-data.ts`) both drop a
|
|
5474
5466
|
* non-finite point, with a `chart/non-finite-value` warning, before it reaches the chart part.
|
|
@@ -5532,14 +5524,17 @@ function buildXlsxSheet(data, layout) {
|
|
|
5532
5524
|
]) + "\n";
|
|
5533
5525
|
}
|
|
5534
5526
|
/**
|
|
5535
|
-
* Build the standalone `.rels` for a classic chart part:
|
|
5536
|
-
*
|
|
5537
|
-
*
|
|
5527
|
+
* Build the standalone `.rels` for a classic chart part: an `rId1` relationship to the chart's
|
|
5528
|
+
* embedded workbook (`Target`), then one per picture an area fill paints. A media `Target` is
|
|
5529
|
+
* `../media/…` from `ppt/slides/` and from `ppt/charts/` alike, so the slide's reads the same here.
|
|
5530
|
+
* Package write path only: `appendSlides` builds a chart's relationships through the package model
|
|
5531
|
+
* instead.
|
|
5538
5532
|
* @param {string} embeddingTarget - the workbook target, relative to the chart part
|
|
5533
|
+
* @param media - the chart's pictures, {@link SlideRelChart.media}
|
|
5539
5534
|
* @return {string} the chart part's `.rels` XML
|
|
5540
5535
|
*/
|
|
5541
|
-
function buildChartRelsXml(embeddingTarget) {
|
|
5542
|
-
return XML_DECL + relationshipsEl([relationshipEl("rId1", PACKAGE_REL, embeddingTarget)]);
|
|
5536
|
+
function buildChartRelsXml(embeddingTarget, media) {
|
|
5537
|
+
return XML_DECL + relationshipsEl([relationshipEl("rId1", PACKAGE_REL, embeddingTarget), ...(media ?? []).map((picture) => relationshipEl(`rId${picture.rId}`, IMAGE_REL, picture.rel.Target))]);
|
|
5543
5538
|
}
|
|
5544
5539
|
/**
|
|
5545
5540
|
* Build the `.rels` for a chartEx chart part: the embedded workbook (rId1, via `<cx:externalData>`)
|
|
@@ -5592,12 +5587,11 @@ async function createExcelWorksheet(chartObject, zip) {
|
|
|
5592
5587
|
zip.add(`ppt/charts/${names.colorsName}`, bodies.chartEx.colorsXml);
|
|
5593
5588
|
zip.add(`ppt/charts/${names.styleName}`, bodies.chartEx.styleXml);
|
|
5594
5589
|
zip.add("ppt/charts/_rels/" + chartObject.fileName + ".rels", buildChartExRelsXml(embeddingTarget, names.colorsName, names.styleName));
|
|
5595
|
-
} else zip.add("ppt/charts/_rels/" + chartObject.fileName + ".rels", buildChartRelsXml(embeddingTarget));
|
|
5590
|
+
} else zip.add("ppt/charts/_rels/" + chartObject.fileName + ".rels", buildChartRelsXml(embeddingTarget, chartObject.media));
|
|
5596
5591
|
zip.add(`ppt/charts/${chartObject.fileName}`, bodies.chartXml);
|
|
5597
5592
|
return "";
|
|
5598
5593
|
}
|
|
5599
|
-
|
|
5600
|
-
//#region src/gen/extract-charts.ts
|
|
5594
|
+
// src/gen/extract-charts.ts
|
|
5601
5595
|
/**
|
|
5602
5596
|
* Charts: the chart part XML plus its embedded workbook bytes. The chart part's own `.rels`
|
|
5603
5597
|
* (workbook reference) is rebuilt on injection.
|
|
@@ -5609,14 +5603,23 @@ async function createExcelWorksheet(chartObject, zip) {
|
|
|
5609
5603
|
* the classic-or-chartEx choice for the package writer too.
|
|
5610
5604
|
*/
|
|
5611
5605
|
function chartsOf(slide) {
|
|
5612
|
-
return
|
|
5606
|
+
return slide._relsChart.map((rel) => ({
|
|
5613
5607
|
rId: rel.rId,
|
|
5614
5608
|
embeddingBytes: buildEmbeddedWorksheet(rel),
|
|
5615
|
-
...chartPartBodies(rel)
|
|
5609
|
+
...chartPartBodies(rel),
|
|
5610
|
+
pictures: (rel.media ?? []).flatMap((picture) => {
|
|
5611
|
+
const bytes = decodeBase64ToBytes(picture.rel.data);
|
|
5612
|
+
const extn = (picture.rel.extn || "png").toLowerCase();
|
|
5613
|
+
return bytes ? [{
|
|
5614
|
+
rId: picture.rId,
|
|
5615
|
+
bytes,
|
|
5616
|
+
extn,
|
|
5617
|
+
contentType: imageContentType(extn)
|
|
5618
|
+
}] : [];
|
|
5619
|
+
})
|
|
5616
5620
|
}));
|
|
5617
5621
|
}
|
|
5618
|
-
|
|
5619
|
-
//#region src/package/parts/chart.ts
|
|
5622
|
+
// src/package/parts/chart.ts
|
|
5620
5623
|
/** The embedded workbook every chart carries; one Default covers all of them. */
|
|
5621
5624
|
const XLSX_DEFAULT = {
|
|
5622
5625
|
extension: "xlsx",
|
|
@@ -5655,7 +5658,7 @@ function chartOverrides(rel, leadingSpace = false) {
|
|
|
5655
5658
|
const chartContributor = {
|
|
5656
5659
|
order: 30,
|
|
5657
5660
|
parts: { fromTargetRels(target, zip) {
|
|
5658
|
-
return
|
|
5661
|
+
return target._relsChart.map((rel) => createExcelWorksheet(rel, zip));
|
|
5659
5662
|
} },
|
|
5660
5663
|
contentTypes: {
|
|
5661
5664
|
defaults(pres) {
|
|
@@ -5663,21 +5666,20 @@ const chartContributor = {
|
|
|
5663
5666
|
...pres.slides,
|
|
5664
5667
|
...pres.slideLayouts,
|
|
5665
5668
|
pres.masterSlide
|
|
5666
|
-
].some((target) =>
|
|
5669
|
+
].some((target) => target._relsChart.length > 0) ? [XLSX_DEFAULT] : [];
|
|
5667
5670
|
},
|
|
5668
5671
|
perSlide(slide) {
|
|
5669
5672
|
return slide._relsChart.flatMap((rel) => chartOverrides(rel));
|
|
5670
5673
|
},
|
|
5671
5674
|
perLayout(layout) {
|
|
5672
|
-
return
|
|
5675
|
+
return layout._relsChart.flatMap((rel) => chartOverrides(rel, true));
|
|
5673
5676
|
},
|
|
5674
5677
|
trailing(pres) {
|
|
5675
|
-
return
|
|
5678
|
+
return pres.masterSlide._relsChart.flatMap((rel) => chartOverrides(rel, true));
|
|
5676
5679
|
}
|
|
5677
5680
|
}
|
|
5678
5681
|
};
|
|
5679
|
-
|
|
5680
|
-
//#region src/gen/slide/objects/chart.ts
|
|
5682
|
+
// src/gen/slide/objects/chart.ts
|
|
5681
5683
|
/**
|
|
5682
5684
|
* pptx-ts: chart slide-object serialization
|
|
5683
5685
|
*
|
|
@@ -5735,8 +5737,8 @@ function renderChartObject(ctx) {
|
|
|
5735
5737
|
const graphicFrame = graphicFrameEl({
|
|
5736
5738
|
nvGraphicFramePr: el("p:nvGraphicFramePr", null, [
|
|
5737
5739
|
raw(cNvPrEl(shapeId, itemOpts.objectName, itemOpts.altText || "", void 0, { openPrefix: " " })),
|
|
5738
|
-
raw(
|
|
5739
|
-
raw(el("p:nvPr", null, raw(genXmlPlaceholder(placeholderObj)), { openPrefix: " " }))
|
|
5740
|
+
raw(elOrVoid("p:cNvGraphicFramePr", null, genXmlObjectLock("a:graphicFrameLocks", GRAPHIC_FRAME_LOCK_ATTRS, itemOpts.objectLock, itemOpts.objectName), { openPrefix: " " })),
|
|
5741
|
+
raw(el("p:nvPr", null, raw(genXmlPlaceholder(placeholderObj, statedPlaceholderBinding(itemOpts.placeholder))), { openPrefix: " " }))
|
|
5740
5742
|
], {
|
|
5741
5743
|
openPrefix: " ",
|
|
5742
5744
|
closePrefix: " "
|
|
@@ -5772,7 +5774,7 @@ function renderChartObject(ctx) {
|
|
|
5772
5774
|
/**
|
|
5773
5775
|
* Build the `<mc:Fallback>` placeholder shape shown when a chartEx chart cannot be rendered
|
|
5774
5776
|
* (any consumer older than PowerPoint 2016 / Microsoft 365). A light-grey rectangle at the chart's
|
|
5775
|
-
* position carrying a short explanatory note
|
|
5777
|
+
* position carrying a short explanatory note, enough that the slide reads sensibly rather than
|
|
5776
5778
|
* showing a void where the chart would be.
|
|
5777
5779
|
*/
|
|
5778
5780
|
function renderChartExFallback(shapeId, itemOpts, x, y, cx, cy) {
|
|
@@ -5800,8 +5802,7 @@ function renderChartExFallback(shapeId, itemOpts, x, y, cx, cy) {
|
|
|
5800
5802
|
]))
|
|
5801
5803
|
]);
|
|
5802
5804
|
}
|
|
5803
|
-
|
|
5804
|
-
//#region src/gen/define/chart.ts
|
|
5805
|
+
// src/gen/define/chart.ts
|
|
5805
5806
|
/**
|
|
5806
5807
|
* pptx-ts: Chart Definition
|
|
5807
5808
|
*
|
|
@@ -5902,8 +5903,8 @@ function reportMismatchedSeries(options, data) {
|
|
|
5902
5903
|
* object is shared across two charts.
|
|
5903
5904
|
*
|
|
5904
5905
|
* Nested objects are copied wherever a normalizer writes into them. `structuredClone` is
|
|
5905
|
-
* deliberately not used: it would deep-copy the `ChartMulti[]` on `_type
|
|
5906
|
-
* identity the combo emit path depends on
|
|
5906
|
+
* deliberately not used: it would deep-copy the `ChartMulti[]` on `_type`, breaking the series
|
|
5907
|
+
* identity the combo emit path depends on, and throws on a stray function in an untyped
|
|
5907
5908
|
* caller's option bag.
|
|
5908
5909
|
* @param opts - caller-supplied chart options
|
|
5909
5910
|
*/
|
|
@@ -5930,7 +5931,7 @@ function copyChartOptions(opts) {
|
|
|
5930
5931
|
* A border width the emitter can use: a positive, finite number of points.
|
|
5931
5932
|
*
|
|
5932
5933
|
* `0` counts as "not stated" here and takes the default, which is what the truthiness test
|
|
5933
|
-
* this replaces already did. What it adds is `Infinity` and a negative
|
|
5934
|
+
* this replaces already did. What it adds is `Infinity` and a negative. Neither is a width,
|
|
5934
5935
|
* and a negative one reached `a:ln/@w` as a negative attribute.
|
|
5935
5936
|
*/
|
|
5936
5937
|
function isUsableBorderWidth(width) {
|
|
@@ -6142,6 +6143,70 @@ function normalizeAxisOptions(axis, prefix) {
|
|
|
6142
6143
|
}
|
|
6143
6144
|
if (axis.valAxisLogScaleBase != null) axis.valAxisLogScaleBase = clampRangedInput(axis.valAxisLogScaleBase, 2, 1e3, "chart/option-out-of-range", `${prefix}valAxisLogScaleBase`, "chart/option-non-finite");
|
|
6144
6145
|
}
|
|
6146
|
+
/** `YYYY-MM-DD`, optionally with a `THH:MM` or `THH:MM:SS` time (a space works as well as `T`). */
|
|
6147
|
+
const ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?)?$/;
|
|
6148
|
+
/** Days from the spreadsheet epoch (serial 0, 1899-12-30) to the Unix epoch. */
|
|
6149
|
+
const SERIAL_UNIX_EPOCH = 25569;
|
|
6150
|
+
/** 1900-03-01: earlier serials are skewed by the spreadsheet's phantom 1900-02-29. */
|
|
6151
|
+
const FIRST_SAFE_SERIAL = 61;
|
|
6152
|
+
/**
|
|
6153
|
+
* A category label as the date serial a `<c:numCache>` point holds, or `null` when it is not one.
|
|
6154
|
+
*
|
|
6155
|
+
* A number passes, written plainly (`'1e3'` is 1000): it already is a serial. An ISO date or date-time becomes its serial, read
|
|
6156
|
+
* as calendar time, so `'2026-01-01'` is 46023 in every time zone. A date that does not exist, such
|
|
6157
|
+
* as `'2026-02-30'`, or one before 1900-03-01 is not converted.
|
|
6158
|
+
* @param label - one category label, not blank
|
|
6159
|
+
*/
|
|
6160
|
+
function dateCategorySerial(label) {
|
|
6161
|
+
const number = Number(label);
|
|
6162
|
+
if (Number.isFinite(number)) return String(number);
|
|
6163
|
+
const m = ISO_DATE.exec(label.trim());
|
|
6164
|
+
if (!m) return null;
|
|
6165
|
+
const [y, mo, d, h, mi, s] = m.slice(1).map((group) => Number(group ?? 0));
|
|
6166
|
+
if (y === void 0 || mo === void 0 || d === void 0 || h === void 0 || mi === void 0 || s === void 0) return null;
|
|
6167
|
+
const ms = Date.UTC(y, mo - 1, d, h, mi, s);
|
|
6168
|
+
const date = new Date(ms);
|
|
6169
|
+
if (date.getUTCMonth() !== mo - 1 || date.getUTCDate() !== d || h > 23 || mi > 59 || s > 59) return null;
|
|
6170
|
+
const serial = ms / 864e5 + SERIAL_UNIX_EPOCH;
|
|
6171
|
+
return serial >= FIRST_SAFE_SERIAL ? String(serial) : null;
|
|
6172
|
+
}
|
|
6173
|
+
/**
|
|
6174
|
+
* Turn the leaf category labels into date serials when `catLabelFormatCode` makes them dates, or drop
|
|
6175
|
+
* the format code, warning, when one of them is not a date.
|
|
6176
|
+
*
|
|
6177
|
+
* A format code makes the categories a `<c:numRef>` under a `<c:dateAx>`, and its cache was written
|
|
6178
|
+
* from the labels as given. PowerPoint refuses the whole deck (0x80070570) over one `<c:numCache>`
|
|
6179
|
+
* point that is not a number, so `labels: ['2026-01-01', …]` broke the deck it was in. Blank labels
|
|
6180
|
+
* stay blank. Only the leaf level is cached, so it is the only level converted.
|
|
6181
|
+
*
|
|
6182
|
+
* The series' label arrays are replaced, never written through: the outer array is this model's own,
|
|
6183
|
+
* but the inner ones are the caller's.
|
|
6184
|
+
* @param options - the chart's options, `catLabelFormatCode` deleted when the labels are not dates
|
|
6185
|
+
* @param series - every series, a combo's across all its subcharts
|
|
6186
|
+
*/
|
|
6187
|
+
function normalizeDateCategories(options, series) {
|
|
6188
|
+
if (!options.catLabelFormatCode) return;
|
|
6189
|
+
const type = options._type;
|
|
6190
|
+
if (!(Array.isArray(type) || !(isXyChart(type) || type === "pie" || type === "doughnut" || isChartExType(type)))) return;
|
|
6191
|
+
const converted = /* @__PURE__ */ new Map();
|
|
6192
|
+
for (const item of series) {
|
|
6193
|
+
const [leaf, ...outer] = item.labels ?? [];
|
|
6194
|
+
if (!leaf) continue;
|
|
6195
|
+
const serials = [];
|
|
6196
|
+
for (const label of leaf) {
|
|
6197
|
+
const text = label == null ? "" : String(label);
|
|
6198
|
+
const serial = text.trim() === "" ? text : dateCategorySerial(text);
|
|
6199
|
+
if (serial === null) {
|
|
6200
|
+
warn("chart/invalid-option-value", `"catLabelFormatCode" needs category labels that are dates (a serial number or YYYY-MM-DD); "${text}" is neither, so the categories stay text.`);
|
|
6201
|
+
delete options.catLabelFormatCode;
|
|
6202
|
+
return;
|
|
6203
|
+
}
|
|
6204
|
+
serials.push(serial);
|
|
6205
|
+
}
|
|
6206
|
+
converted.set(item, [serials, ...outer]);
|
|
6207
|
+
}
|
|
6208
|
+
for (const [item, labels] of converted) item.labels = labels;
|
|
6209
|
+
}
|
|
6145
6210
|
/**
|
|
6146
6211
|
* Drop each `x`/`y`/`w`/`h` of a manual layout that is not a fraction of the chart, warning, so that
|
|
6147
6212
|
* axis stays automatic. Shared by the plot area's `layout` and `legendLayout`; the legend's used to
|
|
@@ -6502,6 +6567,77 @@ function normalizeComboSubchartOptions(subOptions, chartOptions, subType, caller
|
|
|
6502
6567
|
return result;
|
|
6503
6568
|
}
|
|
6504
6569
|
/**
|
|
6570
|
+
* The `TextBaseProps` keys `ChartOpts` takes through `ChartPropsTitle` and the chart writer reads
|
|
6571
|
+
* none of: every one but `lang`. The chart's text is styled through its own spellings
|
|
6572
|
+
* (`titleBold`, `legendFontSize`, `dataLabelColor`, …).
|
|
6573
|
+
*/
|
|
6574
|
+
const UNREAD_TEXT_BASE_KEYS = [
|
|
6575
|
+
"align",
|
|
6576
|
+
"bold",
|
|
6577
|
+
"breakLine",
|
|
6578
|
+
"bullet",
|
|
6579
|
+
"caps",
|
|
6580
|
+
"color",
|
|
6581
|
+
"fontFace",
|
|
6582
|
+
"fontFaceEA",
|
|
6583
|
+
"fontSize",
|
|
6584
|
+
"highlight",
|
|
6585
|
+
"italic",
|
|
6586
|
+
"paraIndent",
|
|
6587
|
+
"paraMarginLeft",
|
|
6588
|
+
"softBreakBefore",
|
|
6589
|
+
"tabStops",
|
|
6590
|
+
"textDirection",
|
|
6591
|
+
"textWarp",
|
|
6592
|
+
"transparency",
|
|
6593
|
+
"underline",
|
|
6594
|
+
"valign"
|
|
6595
|
+
];
|
|
6596
|
+
/**
|
|
6597
|
+
* Name the `TextBaseProps` keys a chart was given, which write nothing (#138). A chart written with
|
|
6598
|
+
* `bold` or `fontFace` was byte-identical to one written without, and nothing said so; autocomplete
|
|
6599
|
+
* offers them on `addChart`.
|
|
6600
|
+
* @param options - the chart's options as the caller stated them
|
|
6601
|
+
*/
|
|
6602
|
+
function reportTextBaseKeys(options) {
|
|
6603
|
+
const stated = UNREAD_TEXT_BASE_KEYS.filter((key) => options[key] !== void 0);
|
|
6604
|
+
if (stated.length === 0) return;
|
|
6605
|
+
warn("chart/option-not-supported", `addChart: ${stated.map((key) => `"${key}"`).join(", ")} ${stated.length === 1 ? "has" : "have"} no effect on a chart, whose text is styled through its own options (titleBold, legendFontSize, dataLabelColor, catAxisLabelFontFace, …).`);
|
|
6606
|
+
}
|
|
6607
|
+
/**
|
|
6608
|
+
* Register a chart or plot area's picture fill, so the chart part can reference it.
|
|
6609
|
+
*
|
|
6610
|
+
* The fill wrote nothing and warned that its `image.data` was missing, because a picture fill needs
|
|
6611
|
+
* a media relationship and nothing gave the chart part one (#139). The picture is registered on the
|
|
6612
|
+
* slide, marked {@link SlideRelMedia.chartOwned}, so it is loaded, deduped and written like any other
|
|
6613
|
+
* picture, and the chart part declares it from `rId2` on: its `rId1` is the embedded workbook. The
|
|
6614
|
+
* fill each area keeps is a copy carrying that chart-part id.
|
|
6615
|
+
* @param target - the slide, layout or master the chart is on
|
|
6616
|
+
* @param options - the chart's normalized options, whose `chartArea` and `plotArea` are its own copies
|
|
6617
|
+
* @returns the pictures the chart part references, in relationship-id order
|
|
6618
|
+
*/
|
|
6619
|
+
function registerAreaPictures(target, options) {
|
|
6620
|
+
const media = [];
|
|
6621
|
+
for (const area of [options.chartArea, options.plotArea]) {
|
|
6622
|
+
const fill = area?.fill;
|
|
6623
|
+
if (!area || !fill || typeof fill !== "object" || resolveFillKind(fill) !== "image") continue;
|
|
6624
|
+
const own = { ...fill };
|
|
6625
|
+
const before = target._relsMedia.length;
|
|
6626
|
+
registerImageFillMedia(target, own);
|
|
6627
|
+
const rel = target._relsMedia[before];
|
|
6628
|
+
if (rel && own.type === "image") {
|
|
6629
|
+
rel.chartOwned = true;
|
|
6630
|
+
own._imgRid = media.length + 2;
|
|
6631
|
+
media.push({
|
|
6632
|
+
rId: own._imgRid,
|
|
6633
|
+
rel
|
|
6634
|
+
});
|
|
6635
|
+
}
|
|
6636
|
+
area.fill = own;
|
|
6637
|
+
}
|
|
6638
|
+
return media;
|
|
6639
|
+
}
|
|
6640
|
+
/**
|
|
6505
6641
|
* Generate the chart based on input data.
|
|
6506
6642
|
* OOXML Chart Spec: ISO/IEC 29500-1:2016(E)
|
|
6507
6643
|
*
|
|
@@ -6527,6 +6663,14 @@ function normalizeComboSubchartOptions(subOptions, chartOptions, subType, caller
|
|
|
6527
6663
|
* }
|
|
6528
6664
|
*/
|
|
6529
6665
|
function addChartDefinition(target, type, data, opt) {
|
|
6666
|
+
const [only] = Array.isArray(type) && type.length === 1 ? type : [];
|
|
6667
|
+
if (only && isChartType(only.type) && isBubbleChart(asChartType(only.type))) {
|
|
6668
|
+
const chartOpts = !Array.isArray(data) && data && typeof data === "object" ? data : opt;
|
|
6669
|
+
return addChartDefinition(target, only.type, only.data, {
|
|
6670
|
+
...chartOpts,
|
|
6671
|
+
...only.options
|
|
6672
|
+
});
|
|
6673
|
+
}
|
|
6530
6674
|
const chartId = target._relsChart.length + 1;
|
|
6531
6675
|
const resultObject = { _type: "chart" };
|
|
6532
6676
|
let tmpOpt;
|
|
@@ -6539,7 +6683,8 @@ function addChartDefinition(target, type, data, opt) {
|
|
|
6539
6683
|
tmpData = tmpData.concat(seriesData);
|
|
6540
6684
|
return {
|
|
6541
6685
|
...obj,
|
|
6542
|
-
data: seriesData
|
|
6686
|
+
data: seriesData,
|
|
6687
|
+
options: obj.options ?? {}
|
|
6543
6688
|
};
|
|
6544
6689
|
});
|
|
6545
6690
|
tmpOpt = !Array.isArray(data) && data && typeof data === "object" ? data : opt;
|
|
@@ -6552,8 +6697,16 @@ function addChartDefinition(target, type, data, opt) {
|
|
|
6552
6697
|
for (const name of tmpTypes ? tmpTypes.map((sub) => sub.type) : [type]) if (!isChartType(name)) throw new InvalidOptionError("chart/unknown-type", `addChart: "${String(name)}" is not a chart type. Valid types are: ${Object.values(ChartType).join(", ")}.`, { detail: { type: name } });
|
|
6553
6698
|
if (tmpTypes?.some((sub) => isBubbleChart(asChartType(sub.type)))) throw new InvalidOptionError("chart/bubble-in-combo", "addChart: a bubble chart cannot be combined with other chart types; PowerPoint refuses the deck. Add it as a chart of its own.", { detail: { types: tmpTypes.map((sub) => sub.type) } });
|
|
6554
6699
|
if (!tmpTypes && isChartExType(type)) reportChartExOptions(options, asChartType(type));
|
|
6700
|
+
reportTextBaseKeys(options);
|
|
6555
6701
|
options._type = tmpTypes ?? asChartType(type);
|
|
6556
|
-
|
|
6702
|
+
checkPlaceholderBinding(options.placeholder, "addChart");
|
|
6703
|
+
const placeholder = placeholderFrame(target._slideLayout, options.placeholder);
|
|
6704
|
+
Object.assign(options, resolveAuthoredFrame({
|
|
6705
|
+
x: options.x ?? placeholder.x,
|
|
6706
|
+
y: options.y ?? placeholder.y,
|
|
6707
|
+
w: options.w ?? placeholder.w,
|
|
6708
|
+
h: options.h ?? placeholder.h
|
|
6709
|
+
}, {
|
|
6557
6710
|
x: 1,
|
|
6558
6711
|
y: 1,
|
|
6559
6712
|
w: "50%",
|
|
@@ -6572,6 +6725,7 @@ function addChartDefinition(target, type, data, opt) {
|
|
|
6572
6725
|
normalizeAxisOptions(options, "");
|
|
6573
6726
|
options.catAxes?.forEach((axis, idx) => normalizeAxisOptions(axis, `catAxes[${idx}].`));
|
|
6574
6727
|
options.valAxes?.forEach((axis, idx) => normalizeAxisOptions(axis, `valAxes[${idx}].`));
|
|
6728
|
+
normalizeDateCategories(options, tmpData);
|
|
6575
6729
|
const scatterGrid = {
|
|
6576
6730
|
color: "D9D9D9",
|
|
6577
6731
|
width: 1
|
|
@@ -6603,10 +6757,10 @@ function addChartDefinition(target, type, data, opt) {
|
|
|
6603
6757
|
if (tmpData.length !== expected) warn("chart/stock-series-count", `stock chart style "${options.stockStyle}" expects ${expected} data series (got ${tmpData.length}); the chart may not render as intended.`);
|
|
6604
6758
|
}
|
|
6605
6759
|
reportMismatchedSeries(options, tmpData);
|
|
6606
|
-
resultObject._type = "chart";
|
|
6607
6760
|
resultObject.options = options;
|
|
6608
|
-
resultObject.chartRid = getNewRelId(target);
|
|
6609
6761
|
const isChartEx = isChartExType(options._type);
|
|
6762
|
+
const media = isChartEx ? [] : registerAreaPictures(target, options);
|
|
6763
|
+
resultObject.chartRid = getNewRelId(target);
|
|
6610
6764
|
const { fileName, target: chartTarget } = chartPartNames(chartId, isChartEx);
|
|
6611
6765
|
target._relsChart.push({
|
|
6612
6766
|
rId: getNewRelId(target),
|
|
@@ -6616,13 +6770,13 @@ function addChartDefinition(target, type, data, opt) {
|
|
|
6616
6770
|
globalId: chartId,
|
|
6617
6771
|
isChartEx,
|
|
6618
6772
|
fileName,
|
|
6619
|
-
Target: chartTarget
|
|
6773
|
+
Target: chartTarget,
|
|
6774
|
+
...media.length > 0 ? { media } : {}
|
|
6620
6775
|
});
|
|
6621
6776
|
target._slideObjects.push(resultObject);
|
|
6622
6777
|
return resultObject;
|
|
6623
6778
|
}
|
|
6624
|
-
|
|
6625
|
-
//#region src/families/chart.ts
|
|
6779
|
+
// src/families/chart.ts
|
|
6626
6780
|
/**
|
|
6627
6781
|
* pptx-ts: the chart construct family
|
|
6628
6782
|
*
|
|
@@ -6660,97 +6814,7 @@ const chartFamily = {
|
|
|
6660
6814
|
parts: chartContributor,
|
|
6661
6815
|
extract: { charts: chartsOf }
|
|
6662
6816
|
};
|
|
6663
|
-
|
|
6664
|
-
//#region src/gen/slide/comments.ts
|
|
6665
|
-
/**
|
|
6666
|
-
* pptx-ts: comment parts
|
|
6667
|
-
*
|
|
6668
|
-
* Resolve every slide's comments into a deck-wide author registry with per-author
|
|
6669
|
-
* numbering, then emit the presentation-level `commentAuthors.xml` and each
|
|
6670
|
-
* slide's `comments/commentN.xml` part.
|
|
6671
|
-
*/
|
|
6672
|
-
/**
|
|
6673
|
-
* Walk every slide's comments and build the deck-wide author registry + per-comment numbering.
|
|
6674
|
-
*
|
|
6675
|
-
* Legacy comments number each comment with a *per-author* 1-based `idx`; an author's `lastIdx` is the
|
|
6676
|
-
* highest `idx` it used. Authors are keyed by `name`+`initials` and assigned ids in first-appearance
|
|
6677
|
-
* order (slide order, then insertion order). `clrIdx` mirrors `id` (one colour slot per author).
|
|
6678
|
-
* @param {PresSlideInternal[]} slides - all presentation slides
|
|
6679
|
-
* @return {ResolvedComments} the author list and per-comment metadata
|
|
6680
|
-
*/
|
|
6681
|
-
function resolveCommentAuthors(slides) {
|
|
6682
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
6683
|
-
const authors = [];
|
|
6684
|
-
const perAuthorCount = /* @__PURE__ */ new Map();
|
|
6685
|
-
const meta = /* @__PURE__ */ new Map();
|
|
6686
|
-
(slides || []).forEach((slide) => {
|
|
6687
|
-
(slide._comments || []).forEach((comment) => {
|
|
6688
|
-
const key = comment.author + "\0" + comment.initials;
|
|
6689
|
-
let author = byKey.get(key);
|
|
6690
|
-
if (!author) {
|
|
6691
|
-
author = {
|
|
6692
|
-
id: authors.length,
|
|
6693
|
-
name: comment.author,
|
|
6694
|
-
initials: comment.initials,
|
|
6695
|
-
lastIdx: 0,
|
|
6696
|
-
clrIdx: authors.length
|
|
6697
|
-
};
|
|
6698
|
-
byKey.set(key, author);
|
|
6699
|
-
authors.push(author);
|
|
6700
|
-
perAuthorCount.set(author.id, 0);
|
|
6701
|
-
}
|
|
6702
|
-
const idx = (perAuthorCount.get(author.id) ?? 0) + 1;
|
|
6703
|
-
perAuthorCount.set(author.id, idx);
|
|
6704
|
-
author.lastIdx = idx;
|
|
6705
|
-
meta.set(comment, {
|
|
6706
|
-
authorId: author.id,
|
|
6707
|
-
idx
|
|
6708
|
-
});
|
|
6709
|
-
});
|
|
6710
|
-
});
|
|
6711
|
-
return {
|
|
6712
|
-
authors,
|
|
6713
|
-
meta
|
|
6714
|
-
};
|
|
6715
|
-
}
|
|
6716
|
-
/**
|
|
6717
|
-
* Creates the presentation-level `ppt/commentAuthors.xml` part (`<p:cmAuthorLst>`).
|
|
6718
|
-
* @param {ResolvedCommentAuthor[]} authors - resolved deck-wide author registry
|
|
6719
|
-
* @return {string} XML
|
|
6720
|
-
*/
|
|
6721
|
-
function makeXmlCommentAuthors(authors) {
|
|
6722
|
-
const cmAuthors = authors.map((author) => voidEl("p:cmAuthor", {
|
|
6723
|
-
id: author.id,
|
|
6724
|
-
name: author.name,
|
|
6725
|
-
initials: author.initials,
|
|
6726
|
-
lastIdx: author.lastIdx,
|
|
6727
|
-
clrIdx: author.clrIdx
|
|
6728
|
-
})).join("");
|
|
6729
|
-
return XML_DECL + "\r\n" + el("p:cmAuthorLst", { ...PML_ROOT_NS }, raw(cmAuthors));
|
|
6730
|
-
}
|
|
6731
|
-
/**
|
|
6732
|
-
* Creates a per-slide comments part `ppt/comments/comment{N}.xml` (`<p:cmLst>`).
|
|
6733
|
-
* @param {PresSlideInternal} slide - the slide whose comments are serialized
|
|
6734
|
-
* @param {Map} meta - per-comment `authorId`/`idx` from {@link resolveCommentAuthors}
|
|
6735
|
-
* @return {string} XML
|
|
6736
|
-
*/
|
|
6737
|
-
function makeXmlComments(slide, meta) {
|
|
6738
|
-
const cms = (slide._comments || []).map((comment) => {
|
|
6739
|
-
const m = meta.get(comment);
|
|
6740
|
-
if (!m) return "";
|
|
6741
|
-
return el("p:cm", {
|
|
6742
|
-
authorId: m.authorId,
|
|
6743
|
-
dt: comment.date || null,
|
|
6744
|
-
idx: m.idx
|
|
6745
|
-
}, [raw(voidEl("p:pos", {
|
|
6746
|
-
x: Math.round(inch2Emu(comment.x)),
|
|
6747
|
-
y: Math.round(inch2Emu(comment.y))
|
|
6748
|
-
})), raw(el("p:text", null, comment.text))]);
|
|
6749
|
-
}).join("");
|
|
6750
|
-
return XML_DECL + "\r\n" + el("p:cmLst", { ...PML_ROOT_NS }, raw(cms));
|
|
6751
|
-
}
|
|
6752
|
-
//#endregion
|
|
6753
|
-
//#region src/package/parts/comments.ts
|
|
6817
|
+
// src/package/parts/comments.ts
|
|
6754
6818
|
const COMMENT_AUTHORS_PATH = "ppt/commentAuthors.xml";
|
|
6755
6819
|
const commentsContributor = {
|
|
6756
6820
|
order: 20,
|
|
@@ -6759,13 +6823,13 @@ const commentsContributor = {
|
|
|
6759
6823
|
if (resolved.authors.length === 0) return;
|
|
6760
6824
|
zip.add(COMMENT_AUTHORS_PATH, makeXmlCommentAuthors(resolved.authors));
|
|
6761
6825
|
pres.slides.forEach((slide, idx) => {
|
|
6762
|
-
if (
|
|
6826
|
+
if (slide._comments.length > 0) zip.add(commentPath(idx + 1), makeXmlComments(slide._comments, resolved.meta));
|
|
6763
6827
|
});
|
|
6764
6828
|
} },
|
|
6765
6829
|
contentTypes: { trailing(pres) {
|
|
6766
6830
|
const entries = [];
|
|
6767
6831
|
pres.slides.forEach((slide, idx) => {
|
|
6768
|
-
if (
|
|
6832
|
+
if (slide._comments.length > 0) entries.push({
|
|
6769
6833
|
partName: overrideName(commentPath(idx + 1)),
|
|
6770
6834
|
contentType: COMMENTS_CONTENT_TYPE
|
|
6771
6835
|
});
|
|
@@ -6777,8 +6841,7 @@ const commentsContributor = {
|
|
|
6777
6841
|
return entries;
|
|
6778
6842
|
} }
|
|
6779
6843
|
};
|
|
6780
|
-
|
|
6781
|
-
//#region src/gen/define/comment.ts
|
|
6844
|
+
// src/gen/define/comment.ts
|
|
6782
6845
|
/**
|
|
6783
6846
|
* pptx-ts: Comment Definition
|
|
6784
6847
|
*
|
|
@@ -6819,7 +6882,6 @@ function addCommentDefinition(target, opts) {
|
|
|
6819
6882
|
let date;
|
|
6820
6883
|
if (opts.date instanceof Date) date = opts.date.toISOString();
|
|
6821
6884
|
else if (typeof opts.date === "string" && opts.date) date = opts.date;
|
|
6822
|
-
if (!target._comments) target._comments = [];
|
|
6823
6885
|
target._comments.push(date === void 0 ? {
|
|
6824
6886
|
author,
|
|
6825
6887
|
initials,
|
|
@@ -6835,8 +6897,7 @@ function addCommentDefinition(target, opts) {
|
|
|
6835
6897
|
date
|
|
6836
6898
|
});
|
|
6837
6899
|
}
|
|
6838
|
-
|
|
6839
|
-
//#region src/families/comments.ts
|
|
6900
|
+
// src/families/comments.ts
|
|
6840
6901
|
/**
|
|
6841
6902
|
* pptx-ts: the comments construct family
|
|
6842
6903
|
*
|
|
@@ -6850,8 +6911,7 @@ const commentsFamily = {
|
|
|
6850
6911
|
} },
|
|
6851
6912
|
parts: commentsContributor
|
|
6852
6913
|
};
|
|
6853
|
-
|
|
6854
|
-
//#region src/gen/slide/objects/connector.ts
|
|
6914
|
+
// src/gen/slide/objects/connector.ts
|
|
6855
6915
|
/**
|
|
6856
6916
|
* pptx-ts: connector slide-object serialization
|
|
6857
6917
|
*
|
|
@@ -6901,8 +6961,7 @@ function renderConnectorObject(ctx) {
|
|
|
6901
6961
|
strSlideXml += "</p:spPr></p:cxnSp>";
|
|
6902
6962
|
return strSlideXml;
|
|
6903
6963
|
}
|
|
6904
|
-
|
|
6905
|
-
//#region src/gen/define/connector.ts
|
|
6964
|
+
// src/gen/define/connector.ts
|
|
6906
6965
|
/**
|
|
6907
6966
|
* pptx-ts: Connector Definition
|
|
6908
6967
|
*
|
|
@@ -6994,8 +7053,7 @@ function addConnectorDefinition(target, opts) {
|
|
|
6994
7053
|
};
|
|
6995
7054
|
target._slideObjects.push(newObject);
|
|
6996
7055
|
}
|
|
6997
|
-
|
|
6998
|
-
//#region src/families/connector.ts
|
|
7056
|
+
// src/families/connector.ts
|
|
6999
7057
|
const connectorFamily = {
|
|
7000
7058
|
name: "connector",
|
|
7001
7059
|
authors: { addConnector(slide, options) {
|
|
@@ -7003,8 +7061,7 @@ const connectorFamily = {
|
|
|
7003
7061
|
} },
|
|
7004
7062
|
renderers: { ["connector"]: renderConnectorObject }
|
|
7005
7063
|
};
|
|
7006
|
-
|
|
7007
|
-
//#region src/families/measure.ts
|
|
7064
|
+
// src/families/measure.ts
|
|
7008
7065
|
/**
|
|
7009
7066
|
* pptx-ts: the measurement construct family
|
|
7010
7067
|
*
|
|
@@ -7039,14 +7096,13 @@ const measureFamily = {
|
|
|
7039
7096
|
}
|
|
7040
7097
|
}
|
|
7041
7098
|
};
|
|
7042
|
-
|
|
7043
|
-
//#region src/gen/slide/objects/media.ts
|
|
7099
|
+
// src/gen/slide/objects/media.ts
|
|
7044
7100
|
/**
|
|
7045
7101
|
* pptx-ts: media (audio / video / online video) slide-object serialization
|
|
7046
7102
|
*
|
|
7047
7103
|
* Emits a `media` slide object as a `<p:pic>` carrying the required preview image. The online
|
|
7048
|
-
* and embedded forms differ in exactly two tokens
|
|
7049
|
-
* paired `<p14:media>` rel binds by `r:link` or `r:embed`
|
|
7104
|
+
* and embedded forms differ in exactly two tokens (the EG_Media choice element and whether the
|
|
7105
|
+
* paired `<p14:media>` rel binds by `r:link` or `r:embed`), so they share one body.
|
|
7050
7106
|
*/
|
|
7051
7107
|
/**
|
|
7052
7108
|
* Render a `media` (audio/video/online) slide object to its `<p:pic>` XML.
|
|
@@ -7095,8 +7151,7 @@ function renderMediaObject(ctx) {
|
|
|
7095
7151
|
}))
|
|
7096
7152
|
]);
|
|
7097
7153
|
}
|
|
7098
|
-
|
|
7099
|
-
//#region src/families/media.ts
|
|
7154
|
+
// src/families/media.ts
|
|
7100
7155
|
const mediaFamily = {
|
|
7101
7156
|
name: "media",
|
|
7102
7157
|
authors: { addMedia(slide, options) {
|
|
@@ -7104,14 +7159,13 @@ const mediaFamily = {
|
|
|
7104
7159
|
} },
|
|
7105
7160
|
renderers: { ["media"]: renderMediaObject }
|
|
7106
7161
|
};
|
|
7107
|
-
|
|
7108
|
-
//#region src/gen/slide/objects/model3d.ts
|
|
7162
|
+
// src/gen/slide/objects/model3d.ts
|
|
7109
7163
|
/** The `am3d` namespace, doubling as `a:graphicData@uri` and the `mc:Choice Requires` token's URI. */
|
|
7110
7164
|
const AM3D_NS = "http://schemas.microsoft.com/office/drawing/2017/model3d";
|
|
7111
7165
|
/** Denominator of every `am3d` rational element (`@n`/`@d`). */
|
|
7112
7166
|
const RATIO_DEN = 1e6;
|
|
7113
7167
|
/**
|
|
7114
|
-
* `am3d:raster@rName`/`@rVer
|
|
7168
|
+
* `am3d:raster@rName`/`@rVer`: the renderer that produced the cached preview. PowerPoint stamps
|
|
7115
7169
|
* its own renderer here; pptx-ts did not rasterize anything, but the attributes are what PowerPoint
|
|
7116
7170
|
* writes and the element is where the preview blip lives, so they are reproduced verbatim.
|
|
7117
7171
|
*/
|
|
@@ -7124,7 +7178,7 @@ const RASTER = {
|
|
|
7124
7178
|
* gave different values); the cube's is emitted, matching the fixed default camera.
|
|
7125
7179
|
*/
|
|
7126
7180
|
const OBJ_VIEWPORT_SZ = 3338805;
|
|
7127
|
-
/** The three point lights PowerPoint writes for every inserted model
|
|
7181
|
+
/** The three point lights PowerPoint writes for every inserted model: key, fill and rim. */
|
|
7128
7182
|
const PT_LIGHTS = [
|
|
7129
7183
|
{
|
|
7130
7184
|
clr: {
|
|
@@ -7166,7 +7220,7 @@ const PT_LIGHTS = [
|
|
|
7166
7220
|
}
|
|
7167
7221
|
}
|
|
7168
7222
|
];
|
|
7169
|
-
/** `am3d:ambientLight
|
|
7223
|
+
/** `am3d:ambientLight`: neutral 50% scRGB at half illuminance, constant like the point lights. */
|
|
7170
7224
|
const AMBIENT = {
|
|
7171
7225
|
clr: {
|
|
7172
7226
|
r: 5e4,
|
|
@@ -7175,7 +7229,7 @@ const AMBIENT = {
|
|
|
7175
7229
|
},
|
|
7176
7230
|
illuminanceN: 5e5
|
|
7177
7231
|
};
|
|
7178
|
-
/** `<am3d:clr><a:scrgbClr …/></am3d:clr
|
|
7232
|
+
/** `<am3d:clr><a:scrgbClr …/></am3d:clr>`: the colour wrapper both light kinds share. */
|
|
7179
7233
|
function lightColor(clr) {
|
|
7180
7234
|
return el("am3d:clr", null, raw(voidEl("a:scrgbClr", clr)));
|
|
7181
7235
|
}
|
|
@@ -7190,7 +7244,7 @@ function cameraEl(model) {
|
|
|
7190
7244
|
}
|
|
7191
7245
|
/**
|
|
7192
7246
|
* The `am3d:trans` block: model-unit scale plus an identity placement. Only `meterPerModelUnit`
|
|
7193
|
-
* varies
|
|
7247
|
+
* varies; `preTrans`/`scale`/`rot`/`postTrans` are the identity PowerPoint writes for a model
|
|
7194
7248
|
* inserted without any subsequent 3D manipulation, and `am3d:rot` is emitted attribute-less.
|
|
7195
7249
|
*/
|
|
7196
7250
|
function transEl(model) {
|
|
@@ -7235,7 +7289,7 @@ function lightsXml() {
|
|
|
7235
7289
|
raw(voidEl("am3d:pos", light.pos))
|
|
7236
7290
|
])).join("");
|
|
7237
7291
|
}
|
|
7238
|
-
/** The `mc:Fallback` picture
|
|
7292
|
+
/** The `mc:Fallback` picture: the cached preview, drawn by everything that is not PowerPoint 2019+. */
|
|
7239
7293
|
function fallbackPic(picId, objectName, altText, model, xf) {
|
|
7240
7294
|
return el("p:pic", null, [raw(el("p:nvPicPr", null, [
|
|
7241
7295
|
raw(cNvPrEl(picId, objectName, altText)),
|
|
@@ -7255,7 +7309,7 @@ function renderModel3dObject(ctx) {
|
|
|
7255
7309
|
const { obj: slideItemObj, shapeId, frame: { x, y, cx, cy } } = ctx;
|
|
7256
7310
|
const model = slideItemObj.model3d;
|
|
7257
7311
|
if (!model) return "";
|
|
7258
|
-
const opts =
|
|
7312
|
+
const opts = ctx.itemOpts;
|
|
7259
7313
|
const altText = opts.altText || "";
|
|
7260
7314
|
const spPr = el("am3d:spPr", null, [raw(xfrmEl("a:xfrm", {
|
|
7261
7315
|
x: 0,
|
|
@@ -7301,12 +7355,11 @@ function renderModel3dObject(ctx) {
|
|
|
7301
7355
|
})
|
|
7302
7356
|
});
|
|
7303
7357
|
}
|
|
7304
|
-
|
|
7305
|
-
//#region src/gen/define/preview-image.ts
|
|
7358
|
+
// src/gen/define/preview-image.ts
|
|
7306
7359
|
/**
|
|
7307
7360
|
* pptx-ts: preview/cover image registration.
|
|
7308
7361
|
*
|
|
7309
|
-
* Several objects are drawn from a cached raster the library cannot render itself
|
|
7362
|
+
* Several objects are drawn from a cached raster the library cannot render itself: a Zoom tile's
|
|
7310
7363
|
* thumbnail of its target slide, an OLE object's picture of the embedded document, a 3D model's
|
|
7311
7364
|
* preview. Each registers that raster as an ordinary slide image rel and references it by rId.
|
|
7312
7365
|
* Shared here so the definers agree on the placeholder fallback and on extension sniffing; the rel itself goes through
|
|
@@ -7335,8 +7388,7 @@ function registerPreviewImage(target, cover, label) {
|
|
|
7335
7388
|
registerImageMediaRel(target, source, rId);
|
|
7336
7389
|
return rId;
|
|
7337
7390
|
}
|
|
7338
|
-
|
|
7339
|
-
//#region src/gen/define/model3d.ts
|
|
7391
|
+
// src/gen/define/model3d.ts
|
|
7340
7392
|
/** OPC content type for a glTF binary, as PowerPoint spells it in `[Content_Types].xml`. */
|
|
7341
7393
|
const GLB_CONTENT_TYPE = "model/gltf.binary";
|
|
7342
7394
|
/** Fixed-point denominator for `am3d` linear values: `am3d:up@dy="36000000"` is the unit vector. */
|
|
@@ -7345,7 +7397,7 @@ const AM3D_UNIT = 36e6;
|
|
|
7345
7397
|
const AM3D_RATIO_DEN = 1e6;
|
|
7346
7398
|
/**
|
|
7347
7399
|
* The camera PowerPoint wrote for the 2×2×2 cube fixture, in caller units (metres / degrees).
|
|
7348
|
-
* `z` is `sqrt(3)/2 / sin(22.5°)
|
|
7400
|
+
* `z` is `sqrt(3)/2 / sin(22.5°)`: the bounding sphere of a 1-metre cube framed at a 45° fov.
|
|
7349
7401
|
*/
|
|
7350
7402
|
const DEFAULT_CAMERA = {
|
|
7351
7403
|
pos: {
|
|
@@ -7387,7 +7439,8 @@ function resolveCamera(camera, meterPerModelUnit) {
|
|
|
7387
7439
|
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)}.`);
|
|
7388
7440
|
const scale = meterPerModelUnit ?? DEFAULT_METER_PER_MODEL_UNIT;
|
|
7389
7441
|
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)}.`);
|
|
7390
|
-
|
|
7442
|
+
const meterPerModelUnitN = Math.round(scale * AM3D_RATIO_DEN);
|
|
7443
|
+
if (meterPerModelUnitN === 0) throw new InvalidOptionError("model3d/invalid-scale", `addModel3d(): meterPerModelUnit ${String(scale)} rounds to 0 at the six decimal places the file stores; use at least 0.0000005.`);
|
|
7391
7444
|
const up = toAm3dUnits(camera?.up, DEFAULT_CAMERA.up, "up");
|
|
7392
7445
|
return {
|
|
7393
7446
|
pos: toAm3dUnits(camera?.pos, DEFAULT_CAMERA.pos, "pos"),
|
|
@@ -7398,7 +7451,7 @@ function resolveCamera(camera, meterPerModelUnit) {
|
|
|
7398
7451
|
dz: up.z
|
|
7399
7452
|
},
|
|
7400
7453
|
fov: Math.round(fovDeg * ANGLE_UNITS_PER_DEGREE),
|
|
7401
|
-
meterPerModelUnitN
|
|
7454
|
+
meterPerModelUnitN
|
|
7402
7455
|
};
|
|
7403
7456
|
}
|
|
7404
7457
|
/**
|
|
@@ -7444,8 +7497,7 @@ function addModel3dDefinition(target, opt) {
|
|
|
7444
7497
|
};
|
|
7445
7498
|
target._slideObjects.push(slideData);
|
|
7446
7499
|
}
|
|
7447
|
-
|
|
7448
|
-
//#region src/families/model3d.ts
|
|
7500
|
+
// src/families/model3d.ts
|
|
7449
7501
|
const model3dFamily = {
|
|
7450
7502
|
name: "model3d",
|
|
7451
7503
|
authors: { addModel3d(slide, options) {
|
|
@@ -7453,12 +7505,11 @@ const model3dFamily = {
|
|
|
7453
7505
|
} },
|
|
7454
7506
|
renderers: { ["model3d"]: renderModel3dObject }
|
|
7455
7507
|
};
|
|
7456
|
-
|
|
7457
|
-
//#region src/gen/slide/objects/ole.ts
|
|
7508
|
+
// src/gen/slide/objects/ole.ts
|
|
7458
7509
|
/**
|
|
7459
7510
|
* pptx-ts: OLE-object slide-object serialization
|
|
7460
7511
|
*/
|
|
7461
|
-
/** VML namespace
|
|
7512
|
+
/** VML namespace, declared by an OLE object's `mc:Choice Requires="v"` (no VML content is emitted). */
|
|
7462
7513
|
const VML_NS = "urn:schemas-microsoft-com:vml";
|
|
7463
7514
|
/** graphicData URI for an embedded OLE object (`<p:oleObj>`). */
|
|
7464
7515
|
const OLE_NS = "http://schemas.openxmlformats.org/presentationml/2006/ole";
|
|
@@ -7470,14 +7521,14 @@ const OLE_NS = "http://schemas.openxmlformats.org/presentationml/2006/ole";
|
|
|
7470
7521
|
* PowerPoint renders by drawing the live embedded document); the `mc:Fallback` repeats it with a
|
|
7471
7522
|
* `<p:pic>` preview so every other consumer shows the cached picture.
|
|
7472
7523
|
*
|
|
7473
|
-
* Note `mc:Choice Requires="v"` only *declares* the VML namespace
|
|
7524
|
+
* Note `mc:Choice Requires="v"` only *declares* the VML namespace. Modern PowerPoint writes no
|
|
7474
7525
|
* `spid` and no `vmlDrawing` part, so neither is emitted here.
|
|
7475
7526
|
*/
|
|
7476
7527
|
function renderOleObject(ctx) {
|
|
7477
7528
|
const { obj: slideItemObj, shapeId, frame: { x, y, cx, cy } } = ctx;
|
|
7478
7529
|
const ole = slideItemObj.ole;
|
|
7479
7530
|
if (!ole) return "";
|
|
7480
|
-
const opts =
|
|
7531
|
+
const opts = ctx.itemOpts;
|
|
7481
7532
|
const oleAttrs = {
|
|
7482
7533
|
name: ole.name,
|
|
7483
7534
|
showAsIcon: xsdBoolIfTrue(ole.showAsIcon),
|
|
@@ -7528,9 +7579,8 @@ function renderOleObject(ctx) {
|
|
|
7528
7579
|
payload: alternateContent
|
|
7529
7580
|
});
|
|
7530
7581
|
}
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
/** Rel type for a generic OLE-server blob — a compound-file `.bin` (ECMA-376 Part 1 §15.2.10). */
|
|
7582
|
+
// src/gen/define/ole.ts
|
|
7583
|
+
/** Rel type for a generic OLE-server blob: a compound-file `.bin` (ECMA-376 Part 1 §15.2.10). */
|
|
7534
7584
|
const OLE_OBJECT_REL = OFFICE_REL + "oleObject";
|
|
7535
7585
|
/**
|
|
7536
7586
|
* Embeddable payload formats, keyed by file extension. The six Office extensions are OPC packages
|
|
@@ -7589,7 +7639,7 @@ const EXTN_BY_CONTENT_TYPE = new Map(Object.entries(OLE_FORMATS).map(([extn, fmt
|
|
|
7589
7639
|
/**
|
|
7590
7640
|
* Resolve the embedded part's extension from whatever the caller gave us, in decreasing order of
|
|
7591
7641
|
* explicitness: `extn`, the `data:` URI's MIME, the `path`'s extension, then the `progId`. Anything
|
|
7592
|
-
* unrecognized becomes `bin`, the generic OLE blob
|
|
7642
|
+
* unrecognized becomes `bin`, the generic OLE blob, which is what PowerPoint itself writes for a
|
|
7593
7643
|
* shell-packaged payload, so an unknown extension never leaks into `[Content_Types].xml`.
|
|
7594
7644
|
*/
|
|
7595
7645
|
function resolvePartExtn(opt) {
|
|
@@ -7668,8 +7718,7 @@ function addOleObjectDefinition(target, opt) {
|
|
|
7668
7718
|
};
|
|
7669
7719
|
target._slideObjects.push(slideData);
|
|
7670
7720
|
}
|
|
7671
|
-
|
|
7672
|
-
//#region src/families/ole.ts
|
|
7721
|
+
// src/families/ole.ts
|
|
7673
7722
|
const oleFamily = {
|
|
7674
7723
|
name: "ole",
|
|
7675
7724
|
authors: { addOleObject(slide, options) {
|
|
@@ -7677,11 +7726,10 @@ const oleFamily = {
|
|
|
7677
7726
|
} },
|
|
7678
7727
|
renderers: { ["oleObject"]: renderOleObject }
|
|
7679
7728
|
};
|
|
7680
|
-
|
|
7681
|
-
//#region src/gen/drawingml/table-border.ts
|
|
7729
|
+
// src/gen/drawingml/table-border.ts
|
|
7682
7730
|
/**
|
|
7683
|
-
* One `<a:lnX>` border element. Every side of a table cell
|
|
7684
|
-
* diagonals
|
|
7731
|
+
* One `<a:lnX>` border element. Every side of a table cell (the four edges and the two
|
|
7732
|
+
* diagonals) is a `CT_LineProperties`, so they differ only in element name.
|
|
7685
7733
|
* @param {string} name - the element's local name (`lnL`, `lnTlToBr`, …)
|
|
7686
7734
|
* @param {BorderProps} border - the resolved border for that side
|
|
7687
7735
|
* @return {string} the border element XML
|
|
@@ -7765,8 +7813,7 @@ function genTableCellBorderXml(cellBorder, diagonal) {
|
|
|
7765
7813
|
if (diagonal?.blToTr) strXml += genBorderLine("lnBlToTr", diagonal.blToTr);
|
|
7766
7814
|
return strXml;
|
|
7767
7815
|
}
|
|
7768
|
-
|
|
7769
|
-
//#region src/gen/drawingml/table-cell3d.ts
|
|
7816
|
+
// src/gen/drawingml/table-cell3d.ts
|
|
7770
7817
|
/**
|
|
7771
7818
|
* Vet one enumerated value before it reaches the XML, reporting and dropping anything outside
|
|
7772
7819
|
* its `ST_` union. See `ooxml/check-enum.ts` for why the write path drops rather than throws.
|
|
@@ -7811,8 +7858,7 @@ function genTableCell3DXml(cell3D) {
|
|
|
7811
7858
|
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 });
|
|
7812
7859
|
return el("a:cell3D", { prstMaterial: resolveEnum(cell3D.material, PRESET_MATERIALS, "material") }, [raw(bevel), lightRig ? raw(lightRig) : null]);
|
|
7813
7860
|
}
|
|
7814
|
-
|
|
7815
|
-
//#region src/gen/slide/objects/table.ts
|
|
7861
|
+
// src/gen/slide/objects/table.ts
|
|
7816
7862
|
/**
|
|
7817
7863
|
* Validate a cell's `horzOverflow` before it reaches the XML, reporting and dropping anything
|
|
7818
7864
|
* outside `ST_TextHorzOverflowType`. `undefined` (the common case) emits nothing.
|
|
@@ -7826,7 +7872,7 @@ function resolveHorzOverflow(value) {
|
|
|
7826
7872
|
* The perimeter is decided per **grid position**, not per authored cell, which is what makes
|
|
7827
7873
|
* merges work: a colspan's origin sits at the left of its span and its covered `_hmerge`
|
|
7828
7874
|
* cells sit to the right, so a span straddling the last column gets that column's rule on the
|
|
7829
|
-
* covered cell
|
|
7875
|
+
* covered cell, exactly where PowerPoint defines a merged region's outer edge. A cell in the
|
|
7830
7876
|
* table's interior touches no edge and comes back untouched.
|
|
7831
7877
|
*
|
|
7832
7878
|
* Returns the input array (not a copy) when nothing applies, so the common no-perimeter path
|
|
@@ -7970,7 +8016,7 @@ function buildMergeGrid(rows, numCols) {
|
|
|
7970
8016
|
* Render a `table` slide object to its `<p:graphicFrame>` XML (merge-grid, row/col spans, per-cell styling).
|
|
7971
8017
|
*/
|
|
7972
8018
|
function renderTableObject(ctx) {
|
|
7973
|
-
const { obj: slideItemObj, shapeId, frame: { x, y, cx, cy }, placeholder: placeholderObj, itemOpts } = ctx;
|
|
8019
|
+
const { obj: slideItemObj, shapeId, slide, frame: { x, y, cx, cy }, placeholder: placeholderObj, itemOpts } = ctx;
|
|
7974
8020
|
let tblInner = "";
|
|
7975
8021
|
const arrTabRows = withCheckedSpans(slideItemObj.arrTabRows ?? []);
|
|
7976
8022
|
const objTabOpts = itemOpts;
|
|
@@ -7981,7 +8027,7 @@ function renderTableObject(ctx) {
|
|
|
7981
8027
|
noGrp: true,
|
|
7982
8028
|
...itemOpts.objectLock
|
|
7983
8029
|
}, itemOpts.objectName)))),
|
|
7984
|
-
raw(el("p:nvPr", null, [raw(genXmlPlaceholder(placeholderObj)), raw(el("p:extLst", null, raw(el("p:ext", { uri: "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}" }, raw(voidEl("p14:modId", {
|
|
8030
|
+
raw(el("p:nvPr", null, [raw(genXmlPlaceholder(placeholderObj, statedPlaceholderBinding(itemOpts.placeholder))), raw(el("p:extLst", null, raw(el("p:ext", { uri: "{D42A27DB-BD31-4B8C-83A1-F6EECF244321}" }, raw(voidEl("p14:modId", {
|
|
7985
8031
|
"xmlns:p14": OOXML_NS.p14,
|
|
7986
8032
|
val: "1579011935"
|
|
7987
8033
|
}))))))], { openPrefix: " " }))
|
|
@@ -8049,6 +8095,10 @@ function renderTableObject(ctx) {
|
|
|
8049
8095
|
return;
|
|
8050
8096
|
}
|
|
8051
8097
|
const cellOpts = inheritTableOptions(cell.options, objTabOpts);
|
|
8098
|
+
if (cellOpts.color === void 0 && itemOpts._slideColor && !cellHasHyperlink(cell)) {
|
|
8099
|
+
const color = objTabOpts.tableStyle ? "color" in slide && slide.color || void 0 : slideTextColor(slide);
|
|
8100
|
+
if (color) cellOpts.color = color;
|
|
8101
|
+
}
|
|
8052
8102
|
const cellValign = resolveTextAnchor(cellOpts.valign);
|
|
8053
8103
|
const cellTextDir = cellOpts.textDirection && cellOpts.textDirection !== "horz" ? cellOpts.textDirection : null;
|
|
8054
8104
|
rejectEmptyColor(cellOpts.fill, "cell fill");
|
|
@@ -8091,14 +8141,13 @@ function renderTableObject(ctx) {
|
|
|
8091
8141
|
}
|
|
8092
8142
|
});
|
|
8093
8143
|
}
|
|
8094
|
-
|
|
8095
|
-
//#region src/gen/define/table.ts
|
|
8144
|
+
// src/gen/define/table.ts
|
|
8096
8145
|
/**
|
|
8097
8146
|
* pptx-ts: Table Definition
|
|
8098
8147
|
*
|
|
8099
8148
|
* `addTableDefinition` applies the `headerRow` / `columns` sugar, normalizes rows into
|
|
8100
|
-
* fully-resolved `TableCellInternal`s (incl. 4-side borders), computes width, and
|
|
8101
|
-
* set
|
|
8149
|
+
* fully-resolved `TableCellInternal`s (incl. 4-side borders), computes width, and (when `autoPage` is
|
|
8150
|
+
* set) shreds the table across overflow slides via `getSlidesForTableRows`.
|
|
8102
8151
|
*/
|
|
8103
8152
|
/**
|
|
8104
8153
|
* Expand a cell/table border into the 4-side tuple the rest of the pipeline expects.
|
|
@@ -8162,13 +8211,12 @@ function applyTableHeaderColumnSugar(tableRows, opt) {
|
|
|
8162
8211
|
const hdr = opt.headerRow && typeof opt.headerRow === "object" ? opt.headerRow : void 0;
|
|
8163
8212
|
const cols = Array.isArray(opt.columns) && opt.columns.length ? opt.columns : void 0;
|
|
8164
8213
|
let srcRows = tableRows;
|
|
8165
|
-
if (
|
|
8214
|
+
if (hdr || cols) {
|
|
8166
8215
|
if (hdr && opt.hasHeader === void 0) opt.hasHeader = true;
|
|
8167
8216
|
const gridRows = tableRows;
|
|
8168
8217
|
const gridCols = gridRows.map(() => []);
|
|
8169
8218
|
if (cols) for (const placement of walkTableGrid(gridRows, tableColCount(gridRows))) gridCols[placement.row]?.push(placement.col);
|
|
8170
8219
|
srcRows = tableRows.map((row, rowIdx) => {
|
|
8171
|
-
if (!Array.isArray(row)) return row;
|
|
8172
8220
|
if (!cols && rowIdx !== 0) return row;
|
|
8173
8221
|
return row.map((cell, cellIdx) => {
|
|
8174
8222
|
const cellObj = typeof cell === "string" || typeof cell === "number" ? {
|
|
@@ -8192,6 +8240,25 @@ function applyTableHeaderColumnSugar(tableRows, opt) {
|
|
|
8192
8240
|
return srcRows;
|
|
8193
8241
|
}
|
|
8194
8242
|
/**
|
|
8243
|
+
* Report and drop `textWarp` from the table and its cells, once per call.
|
|
8244
|
+
*
|
|
8245
|
+
* `TableCellProps` takes it from `TextBaseProps`, and a cell's `a:bodyPr` was written empty whatever
|
|
8246
|
+
* it said (#84). PowerPoint has nowhere to put it: setting `TextFrame2.WarpFormat` on a cell throws
|
|
8247
|
+
* "The specified value is out of range" over COM, and a saved cell carries an empty `a:bodyPr`.
|
|
8248
|
+
* (`fit` is different: `'shrink'` is baked into the runs by the measured-fit pass.)
|
|
8249
|
+
* @param rows - the normalized rows, whose option bags are this module's own copies
|
|
8250
|
+
* @param opt - the table's options, also this module's own
|
|
8251
|
+
*/
|
|
8252
|
+
function dropCellTextWarp(rows, opt) {
|
|
8253
|
+
let stated = false;
|
|
8254
|
+
for (const bag of [opt, ...rows.flatMap((row) => row.map((cell) => cell.options ?? {}))]) {
|
|
8255
|
+
if (bag.textWarp === void 0) continue;
|
|
8256
|
+
stated = true;
|
|
8257
|
+
delete bag.textWarp;
|
|
8258
|
+
}
|
|
8259
|
+
if (stated) warn("table/option-not-supported", "addTable: `textWarp` has no effect in a table cell, which PowerPoint does not warp; it was ignored.");
|
|
8260
|
+
}
|
|
8261
|
+
/**
|
|
8195
8262
|
* A text shadow normalized the way `addText` normalizes one, on a bag this module already owns.
|
|
8196
8263
|
* The run emitter reads `_alpha`, which only {@link normalizeShadowOptions} derives from
|
|
8197
8264
|
* `transparency` or an RGBA colour; skipped, a cell's shadow painted at the default alpha
|
|
@@ -8215,7 +8282,7 @@ function normalizeTableRows(srcRows, opt) {
|
|
|
8215
8282
|
const arrRows = [];
|
|
8216
8283
|
srcRows.forEach((row) => {
|
|
8217
8284
|
const newRow = [];
|
|
8218
|
-
|
|
8285
|
+
row.forEach((cell) => {
|
|
8219
8286
|
const newCellOptions = withRunShadow(typeof cell === "object" && cell.options ? { ...cell.options } : {});
|
|
8220
8287
|
const newCell = {
|
|
8221
8288
|
_type: "tablecell",
|
|
@@ -8229,7 +8296,7 @@ function normalizeTableRows(srcRows, opt) {
|
|
|
8229
8296
|
...run,
|
|
8230
8297
|
options: withRunShadow({ ...run.options })
|
|
8231
8298
|
} : { ...run });
|
|
8232
|
-
else
|
|
8299
|
+
else newCell.text = cell.text;
|
|
8233
8300
|
}
|
|
8234
8301
|
if (newCellOptions.border != null && typeof newCellOptions.border !== "object") {
|
|
8235
8302
|
warn("table/invalid-border", "addTable cell `border` option must be an object. Ex: `{border: {type:'none'}}`");
|
|
@@ -8273,7 +8340,7 @@ function normalizeTableRows(srcRows, opt) {
|
|
|
8273
8340
|
* Resolve `autoPageHeaderRows` to a usable count of header rows.
|
|
8274
8341
|
*
|
|
8275
8342
|
* It is a count, so it has to be a whole number, at least one, and no larger than the table
|
|
8276
|
-
* itself
|
|
8343
|
+
* itself: a header taller than the table repeats every row onto every continuation slide and
|
|
8277
8344
|
* leaves no room for body content. Anything else falls back to `1` and reports
|
|
8278
8345
|
* `table/invalid-header-row-count`.
|
|
8279
8346
|
*
|
|
@@ -8299,16 +8366,16 @@ function resolveHeaderRowCount(value, rowCount) {
|
|
|
8299
8366
|
*
|
|
8300
8367
|
* Three fill sources are walked, which between them cover every way a picture reaches a table:
|
|
8301
8368
|
* the resolved cells (per-cell `options.fill`, plus `headerRow` and `columns[i]`, both baked
|
|
8302
|
-
* onto cells by the sugar step above), the table-level `fill`, which is *not* baked
|
|
8303
|
-
* `gen/slide/objects/table.ts` copies it onto each cell at emit time
|
|
8369
|
+
* onto cells by the sugar step above), the table-level `fill`, which is *not* baked
|
|
8370
|
+
* (`gen/slide/objects/table.ts` copies it onto each cell at emit time), and `tableFill`, which
|
|
8304
8371
|
* lands on `a:tblPr` itself and so needs its own relationship for the same reason.
|
|
8305
8372
|
*
|
|
8306
8373
|
* Keyed on fill **object identity**, not on the image source. The sugar spreads its options
|
|
8307
8374
|
* shallowly, so one `headerRow` fill object is shared by every cell it styles; registering
|
|
8308
8375
|
* per cell would mint a redundant relationship each time and let the later call overwrite
|
|
8309
8376
|
* the `_imgRid` the first one stashed. Two cells given separately-authored fills for the
|
|
8310
|
-
* same file still get one relationship each
|
|
8311
|
-
* behave
|
|
8377
|
+
* same file still get one relationship each (matching how two shapes sharing an image
|
|
8378
|
+
* behave), while the bytes are deduped into a single media part downstream.
|
|
8312
8379
|
*
|
|
8313
8380
|
* Must run only after auto-paging has shredded the rows across slides, for the same reason
|
|
8314
8381
|
* `createHyperlinkRels` does: `target` has to be the slide the cell actually lands on, or
|
|
@@ -8353,6 +8420,7 @@ function addTableDefinition(target, tableRows, options) {
|
|
|
8353
8420
|
kind: "table",
|
|
8354
8421
|
supplied: opt.objectName
|
|
8355
8422
|
});
|
|
8423
|
+
checkPlaceholderBinding(opt.placeholder, "addTable");
|
|
8356
8424
|
if (opt.placeholder) {
|
|
8357
8425
|
const placeholder = placeholderFrame(slideLayout, opt.placeholder);
|
|
8358
8426
|
const x = opt.x ?? placeholder.x;
|
|
@@ -8377,12 +8445,14 @@ function addTableDefinition(target, tableRows, options) {
|
|
|
8377
8445
|
delete opt.border;
|
|
8378
8446
|
}
|
|
8379
8447
|
const arrRows = normalizeTableRows(srcRows, opt);
|
|
8448
|
+
dropCellTextWarp(arrRows, opt);
|
|
8380
8449
|
if (opt.x === void 0 || opt.x === null) opt.x = .5;
|
|
8381
8450
|
if (opt.y === void 0 || opt.y === null) opt.y = .5;
|
|
8382
8451
|
opt.fontSize = opt.fontSize || 12;
|
|
8383
8452
|
opt.margin = resolveCellMarginsInches(opt.margin);
|
|
8384
|
-
if (!
|
|
8385
|
-
|
|
8453
|
+
if (!opt.color) {
|
|
8454
|
+
delete opt.color;
|
|
8455
|
+
opt._slideColor = true;
|
|
8386
8456
|
}
|
|
8387
8457
|
if (Array.isArray(opt.border)) opt.border = [
|
|
8388
8458
|
0,
|
|
@@ -8403,7 +8473,8 @@ function addTableDefinition(target, tableRows, options) {
|
|
|
8403
8473
|
opt.autoPage = typeof opt.autoPage === "boolean" ? opt.autoPage : false;
|
|
8404
8474
|
opt.autoPagePlaceholder = typeof opt.autoPagePlaceholder === "boolean" ? opt.autoPagePlaceholder : false;
|
|
8405
8475
|
opt.autoPageRepeatHeader = typeof opt.autoPageRepeatHeader === "boolean" ? opt.autoPageRepeatHeader : false;
|
|
8406
|
-
|
|
8476
|
+
const headerRowCount = resolveHeaderRowCount(opt.autoPageHeaderRows, tableRows.length);
|
|
8477
|
+
opt.autoPageHeaderRows = headerRowCount;
|
|
8407
8478
|
const lineWeight = Number(opt.autoPageLineWeight);
|
|
8408
8479
|
opt.autoPageLineWeight = typeof opt.autoPageLineWeight !== "undefined" && Number.isFinite(lineWeight) ? lineWeight : 0;
|
|
8409
8480
|
if (opt.autoPageLineWeight) {
|
|
@@ -8449,8 +8520,8 @@ function addTableDefinition(target, tableRows, options) {
|
|
|
8449
8520
|
delete opt.colW;
|
|
8450
8521
|
};
|
|
8451
8522
|
if (typeof opt.colW === "string" || typeof opt.colW === "number") spreadUniformColW(opt.colW);
|
|
8452
|
-
else if (
|
|
8453
|
-
else if (
|
|
8523
|
+
else if (Array.isArray(opt.colW) && opt.colW.length === 1 && firstRowColCnt > 1) spreadUniformColW(opt.colW[0]);
|
|
8524
|
+
else if (Array.isArray(opt.colW) && opt.colW.length !== firstRowColCnt) {
|
|
8454
8525
|
warn("table/col-width-count-mismatch", "addTable: mismatch: (colW.length != data.length) Therefore, defaulting to evenly distributed col widths.");
|
|
8455
8526
|
delete opt.colW;
|
|
8456
8527
|
}
|
|
@@ -8469,9 +8540,10 @@ function addTableDefinition(target, tableRows, options) {
|
|
|
8469
8540
|
}
|
|
8470
8541
|
}
|
|
8471
8542
|
const newAutoPagedSlides = [];
|
|
8472
|
-
if (
|
|
8543
|
+
if (!opt.autoPage) {
|
|
8473
8544
|
createHyperlinkRels(target, arrRows, "addTable");
|
|
8474
8545
|
registerTableImageFills(target, arrRows, opt);
|
|
8546
|
+
createBulletImageRels(target, [opt, ...arrRows.flatMap((row) => row.flatMap((cell) => [cell.options, ...Array.isArray(cell.text) ? cell.text.map((run) => run.options) : []]))]);
|
|
8475
8547
|
const { columns: _columns, ...tableObjectOptions } = opt;
|
|
8476
8548
|
target._slideObjects.push({
|
|
8477
8549
|
_type: "table",
|
|
@@ -8479,8 +8551,8 @@ function addTableDefinition(target, tableRows, options) {
|
|
|
8479
8551
|
options: tableObjectOptions
|
|
8480
8552
|
});
|
|
8481
8553
|
} else {
|
|
8482
|
-
if (opt.autoPageRepeatHeader) opt._arrObjTabHeadRows = arrRows.filter((_row, idx) => idx <
|
|
8483
|
-
const sourcePlaceholders = opt.autoPagePlaceholder
|
|
8554
|
+
if (opt.autoPageRepeatHeader) opt._arrObjTabHeadRows = arrRows.filter((_row, idx) => idx < headerRowCount);
|
|
8555
|
+
const sourcePlaceholders = opt.autoPagePlaceholder ? target._slideObjects.filter((obj) => obj._type !== "table" && obj.options?.placeholder) : [];
|
|
8484
8556
|
getSlidesForTableRows(arrRows, opt, presLayout, slideLayout).forEach((slide, idx) => {
|
|
8485
8557
|
let newSlide = target.getSlide(target._slideNum + idx);
|
|
8486
8558
|
if (!newSlide) {
|
|
@@ -8503,18 +8575,519 @@ function addTableDefinition(target, tableRows, options) {
|
|
|
8503
8575
|
}
|
|
8504
8576
|
return newAutoPagedSlides;
|
|
8505
8577
|
}
|
|
8506
|
-
|
|
8507
|
-
|
|
8578
|
+
// src/gen/pres/builtin-table-styles.ts
|
|
8579
|
+
/**
|
|
8580
|
+
* pptx-ts: the built-in table style definitions
|
|
8581
|
+
*
|
|
8582
|
+
* GENERATED by `scripts/gen-builtin-table-styles.mjs` from `test/read/fixtures/table-styles-builtin.pptx`.
|
|
8583
|
+
* Do not edit by hand: re-run the script.
|
|
8584
|
+
*
|
|
8585
|
+
* PowerPoint's own `a:tblStyle` markup for the 74 built-in [MS-OE376] table styles, which it
|
|
8586
|
+
* writes into `ppt/tableStyles.xml` for every style a deck uses. Each body is a template whose
|
|
8587
|
+
* `$0`/`$1` slots take the scheme colour that varies across a family's accent variants; see the
|
|
8588
|
+
* script's header for why.
|
|
8589
|
+
*/
|
|
8590
|
+
/**
|
|
8591
|
+
* Style bodies, the children of `a:tblStyle`, with `$0`/`$1` where a family's accent goes.
|
|
8592
|
+
* @raw-xml-asset Captured verbatim from PowerPoint; not built here, so not a migration target.
|
|
8593
|
+
*/
|
|
8594
|
+
const BODIES = [
|
|
8595
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band2H><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:band2V><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2V><a:lastCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:top><a:ln w=\"38100\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"38100\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow>",
|
|
8596
|
+
"<a:tblBg><a:fillRef idx=\"2\"><a:schemeClr val=\"$0\"/></a:fillRef><a:effectRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:effectRef></a:tblBg><a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:bottom><a:insideH><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:insideH><a:insideV><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:alpha val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band2H><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2H><a:band1V><a:tcStyle><a:tcBdr><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:alpha val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:band2V><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"2\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:bottom><a:insideH><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"2\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:bottom><a:insideH><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right><a:top><a:lnRef idx=\"2\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"2\"><a:schemeClr val=\"$0\"/></a:lnRef></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"2\"><a:schemeClr val=\"lt1\"/></a:lnRef></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow>",
|
|
8597
|
+
"<a:tblBg><a:fillRef idx=\"3\"><a:schemeClr val=\"$0\"/></a:fillRef><a:effectRef idx=\"3\"><a:schemeClr val=\"$0\"/></a:effectRef></a:tblBg><a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"><a:tint val=\"50000\"/></a:schemeClr></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"><a:tint val=\"50000\"/></a:schemeClr></a:lnRef></a:right><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"><a:tint val=\"50000\"/></a:schemeClr></a:lnRef></a:top><a:bottom><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"><a:tint val=\"50000\"/></a:schemeClr></a:lnRef></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"lt1\"><a:alpha val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"lt1\"><a:alpha val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"2\"><a:schemeClr val=\"lt1\"/></a:lnRef></a:left></a:tcBdr></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:right><a:lnRef idx=\"2\"><a:schemeClr val=\"lt1\"/></a:lnRef></a:right></a:tcBdr></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:lnRef idx=\"2\"><a:schemeClr val=\"lt1\"/></a:lnRef></a:top></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:lastRow><a:seCell><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:top><a:ln><a:noFill/></a:ln></a:top></a:tcBdr></a:tcStyle></a:seCell><a:swCell><a:tcStyle><a:tcBdr><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln><a:noFill/></a:ln></a:top></a:tcBdr></a:tcStyle></a:swCell><a:firstRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:bottom><a:lnRef idx=\"3\"><a:schemeClr val=\"lt1\"/></a:lnRef></a:bottom></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:firstRow><a:neCell><a:tcStyle><a:tcBdr><a:bottom><a:ln><a:noFill/></a:ln></a:bottom></a:tcBdr></a:tcStyle></a:neCell>",
|
|
8598
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"tx1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:alpha val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band2H><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:alpha val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:firstRow>",
|
|
8599
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"tx1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr><a:top><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:top><a:bottom><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:bottom></a:tcBdr></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right></a:tcBdr></a:tcStyle></a:band1V><a:band2V><a:tcStyle><a:tcBdr><a:left><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:left><a:right><a:lnRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:lnRef></a:right></a:tcBdr></a:tcStyle></a:band2V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"50800\" cmpd=\"dbl\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top></a:tcBdr></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"bg1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fillRef idx=\"1\"><a:schemeClr val=\"$0\"/></a:fillRef></a:tcStyle></a:firstRow>",
|
|
8600
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"tx1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:alpha val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:alpha val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"50800\" cmpd=\"dbl\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:firstRow>",
|
|
8601
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"50800\" cmpd=\"dbl\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow>",
|
|
8602
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"50800\" cmpd=\"dbl\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:seCell><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/></a:tcStyle></a:seCell><a:swCell><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/></a:tcStyle></a:swCell><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow>",
|
|
8603
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:firstRow>",
|
|
8604
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln><a:noFill/></a:ln></a:top><a:bottom><a:ln><a:noFill/></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"/></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:shade val=\"60000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:shade val=\"60000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:left><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:left></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:shade val=\"60000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:right><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:right></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:shade val=\"60000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:shade val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:seCell><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left></a:tcBdr></a:tcStyle></a:seCell><a:swCell><a:tcStyle><a:tcBdr><a:right><a:ln><a:noFill/></a:ln></a:right></a:tcBdr></a:tcStyle></a:swCell><a:firstRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow><a:neCell><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left></a:tcBdr></a:tcStyle></a:neCell><a:nwCell><a:tcStyle><a:tcBdr><a:right><a:ln><a:noFill/></a:ln></a:right></a:tcBdr></a:tcStyle></a:nwCell>",
|
|
8605
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln><a:noFill/></a:ln></a:top><a:bottom><a:ln><a:noFill/></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"50800\" cmpd=\"dbl\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"$0\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"$1\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow>",
|
|
8606
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"tx1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln><a:noFill/></a:ln></a:top><a:bottom><a:ln><a:noFill/></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl>",
|
|
8607
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"tx1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl>",
|
|
8608
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"/><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"50800\" cmpd=\"dbl\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:seCell><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/></a:tcStyle></a:seCell><a:swCell><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/></a:tcStyle></a:swCell><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow>",
|
|
8609
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln><a:noFill/></a:ln></a:top><a:bottom><a:ln><a:noFill/></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:left><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:left></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"60000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:right><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:right></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"60000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"60000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:seCell><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left></a:tcBdr></a:tcStyle></a:seCell><a:swCell><a:tcStyle><a:tcBdr><a:right><a:ln><a:noFill/></a:ln></a:right></a:tcBdr></a:tcStyle></a:swCell><a:firstRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"25400\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow><a:neCell><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left></a:tcBdr></a:tcStyle></a:neCell><a:nwCell><a:tcStyle><a:tcBdr><a:right><a:ln><a:noFill/></a:ln></a:right></a:tcBdr></a:tcStyle></a:nwCell>",
|
|
8610
|
+
"<a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln><a:noFill/></a:ln></a:top><a:bottom><a:ln><a:noFill/></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:lastCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr/></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"/><a:tcStyle><a:tcBdr><a:top><a:ln w=\"50800\" cmpd=\"dbl\"><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow>"
|
|
8611
|
+
];
|
|
8612
|
+
/** `[styleId, styleName, body index, ...slot values]`, in the order PowerPoint wrote them. */
|
|
8613
|
+
const STYLES = [
|
|
8614
|
+
[
|
|
8615
|
+
"{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}",
|
|
8616
|
+
"Medium Style 2 - Accent 1",
|
|
8617
|
+
0,
|
|
8618
|
+
"accent1"
|
|
8619
|
+
],
|
|
8620
|
+
[
|
|
8621
|
+
"{2D5ABB26-0587-4C30-8999-92F81FD0307C}",
|
|
8622
|
+
"No Style, No Grid",
|
|
8623
|
+
11
|
|
8624
|
+
],
|
|
8625
|
+
[
|
|
8626
|
+
"{5940675A-B579-460E-94D1-54222C63F5DA}",
|
|
8627
|
+
"No Style, Table Grid",
|
|
8628
|
+
12
|
|
8629
|
+
],
|
|
8630
|
+
[
|
|
8631
|
+
"{3C2FFA5D-87B4-456A-9821-1D502468CF0F}",
|
|
8632
|
+
"Themed Style 1 - Accent 1",
|
|
8633
|
+
1,
|
|
8634
|
+
"accent1"
|
|
8635
|
+
],
|
|
8636
|
+
[
|
|
8637
|
+
"{284E427A-3D55-4303-BF80-6455036E1DE7}",
|
|
8638
|
+
"Themed Style 1 - Accent 2",
|
|
8639
|
+
1,
|
|
8640
|
+
"accent2"
|
|
8641
|
+
],
|
|
8642
|
+
[
|
|
8643
|
+
"{69C7853C-536D-4A76-A0AE-DD22124D55A5}",
|
|
8644
|
+
"Themed Style 1 - Accent 3",
|
|
8645
|
+
1,
|
|
8646
|
+
"accent3"
|
|
8647
|
+
],
|
|
8648
|
+
[
|
|
8649
|
+
"{775DCB02-9BB8-47FD-8907-85C794F793BA}",
|
|
8650
|
+
"Themed Style 1 - Accent 4",
|
|
8651
|
+
1,
|
|
8652
|
+
"accent4"
|
|
8653
|
+
],
|
|
8654
|
+
[
|
|
8655
|
+
"{35758FB7-9AC5-4552-8A53-C91805E547FA}",
|
|
8656
|
+
"Themed Style 1 - Accent 5",
|
|
8657
|
+
1,
|
|
8658
|
+
"accent5"
|
|
8659
|
+
],
|
|
8660
|
+
[
|
|
8661
|
+
"{08FB837D-C827-4EFA-A057-4D05807E0F7C}",
|
|
8662
|
+
"Themed Style 1 - Accent 6",
|
|
8663
|
+
1,
|
|
8664
|
+
"accent6"
|
|
8665
|
+
],
|
|
8666
|
+
[
|
|
8667
|
+
"{D113A9D2-9D6B-4929-AA2D-F23B5EE8CBE7}",
|
|
8668
|
+
"Themed Style 2 - Accent 1",
|
|
8669
|
+
2,
|
|
8670
|
+
"accent1"
|
|
8671
|
+
],
|
|
8672
|
+
[
|
|
8673
|
+
"{18603FDC-E32A-4AB5-989C-0864C3EAD2B8}",
|
|
8674
|
+
"Themed Style 2 - Accent 2",
|
|
8675
|
+
2,
|
|
8676
|
+
"accent2"
|
|
8677
|
+
],
|
|
8678
|
+
[
|
|
8679
|
+
"{306799F8-075E-4A3A-A7F6-7FBC6576F1A4}",
|
|
8680
|
+
"Themed Style 2 - Accent 3",
|
|
8681
|
+
2,
|
|
8682
|
+
"accent3"
|
|
8683
|
+
],
|
|
8684
|
+
[
|
|
8685
|
+
"{E269D01E-BC32-4049-B463-5C60D7B0CCD2}",
|
|
8686
|
+
"Themed Style 2 - Accent 4",
|
|
8687
|
+
2,
|
|
8688
|
+
"accent4"
|
|
8689
|
+
],
|
|
8690
|
+
[
|
|
8691
|
+
"{327F97BB-C833-4FB7-BDE5-3F7075034690}",
|
|
8692
|
+
"Themed Style 2 - Accent 5",
|
|
8693
|
+
2,
|
|
8694
|
+
"accent5"
|
|
8695
|
+
],
|
|
8696
|
+
[
|
|
8697
|
+
"{638B1855-1B75-4FBE-930C-398BA8C253C6}",
|
|
8698
|
+
"Themed Style 2 - Accent 6",
|
|
8699
|
+
2,
|
|
8700
|
+
"accent6"
|
|
8701
|
+
],
|
|
8702
|
+
[
|
|
8703
|
+
"{9D7B26C5-4107-4FEC-AEDC-1716B250A1EF}",
|
|
8704
|
+
"Light Style 1",
|
|
8705
|
+
3,
|
|
8706
|
+
"tx1"
|
|
8707
|
+
],
|
|
8708
|
+
[
|
|
8709
|
+
"{3B4B98B0-60AC-42C2-AFA5-B58CD77FA1E5}",
|
|
8710
|
+
"Light Style 1 - Accent 1",
|
|
8711
|
+
3,
|
|
8712
|
+
"accent1"
|
|
8713
|
+
],
|
|
8714
|
+
[
|
|
8715
|
+
"{0E3FDE45-AF77-4B5C-9715-49D594BDF05E}",
|
|
8716
|
+
"Light Style 1 - Accent 2",
|
|
8717
|
+
3,
|
|
8718
|
+
"accent2"
|
|
8719
|
+
],
|
|
8720
|
+
[
|
|
8721
|
+
"{C083E6E3-FA7D-4D7B-A595-EF9225AFEA82}",
|
|
8722
|
+
"Light Style 1 - Accent 3",
|
|
8723
|
+
3,
|
|
8724
|
+
"accent3"
|
|
8725
|
+
],
|
|
8726
|
+
[
|
|
8727
|
+
"{D27102A9-8310-4765-A935-A1911B00CA55}",
|
|
8728
|
+
"Light Style 1 - Accent 4",
|
|
8729
|
+
3,
|
|
8730
|
+
"accent4"
|
|
8731
|
+
],
|
|
8732
|
+
[
|
|
8733
|
+
"{5FD0F851-EC5A-4D38-B0AD-8093EC10F338}",
|
|
8734
|
+
"Light Style 1 - Accent 5",
|
|
8735
|
+
3,
|
|
8736
|
+
"accent5"
|
|
8737
|
+
],
|
|
8738
|
+
[
|
|
8739
|
+
"{68D230F3-CF80-4859-8CE7-A43EE81993B5}",
|
|
8740
|
+
"Light Style 1 - Accent 6",
|
|
8741
|
+
3,
|
|
8742
|
+
"accent6"
|
|
8743
|
+
],
|
|
8744
|
+
[
|
|
8745
|
+
"{7E9639D4-E3E2-4D34-9284-5A2195B3D0D7}",
|
|
8746
|
+
"Light Style 2",
|
|
8747
|
+
4,
|
|
8748
|
+
"tx1"
|
|
8749
|
+
],
|
|
8750
|
+
[
|
|
8751
|
+
"{69012ECD-51FC-41F1-AA8D-1B2483CD663E}",
|
|
8752
|
+
"Light Style 2 - Accent 1",
|
|
8753
|
+
4,
|
|
8754
|
+
"accent1"
|
|
8755
|
+
],
|
|
8756
|
+
[
|
|
8757
|
+
"{72833802-FEF1-4C79-8D5D-14CF1EAF98D9}",
|
|
8758
|
+
"Light Style 2 - Accent 2",
|
|
8759
|
+
4,
|
|
8760
|
+
"accent2"
|
|
8761
|
+
],
|
|
8762
|
+
[
|
|
8763
|
+
"{F2DE63D5-997A-4646-A377-4702673A728D}",
|
|
8764
|
+
"Light Style 2 - Accent 3",
|
|
8765
|
+
4,
|
|
8766
|
+
"accent3"
|
|
8767
|
+
],
|
|
8768
|
+
[
|
|
8769
|
+
"{17292A2E-F333-43FB-9621-5CBBE7FDCDCB}",
|
|
8770
|
+
"Light Style 2 - Accent 4",
|
|
8771
|
+
4,
|
|
8772
|
+
"accent4"
|
|
8773
|
+
],
|
|
8774
|
+
[
|
|
8775
|
+
"{5A111915-BE36-4E01-A7E5-04B1672EAD32}",
|
|
8776
|
+
"Light Style 2 - Accent 5",
|
|
8777
|
+
4,
|
|
8778
|
+
"accent5"
|
|
8779
|
+
],
|
|
8780
|
+
[
|
|
8781
|
+
"{912C8C85-51F0-491E-9774-3900AFEF0FD7}",
|
|
8782
|
+
"Light Style 2 - Accent 6",
|
|
8783
|
+
4,
|
|
8784
|
+
"accent6"
|
|
8785
|
+
],
|
|
8786
|
+
[
|
|
8787
|
+
"{616DA210-FB5B-4158-B5E0-FEB733F419BA}",
|
|
8788
|
+
"Light Style 3",
|
|
8789
|
+
5,
|
|
8790
|
+
"tx1"
|
|
8791
|
+
],
|
|
8792
|
+
[
|
|
8793
|
+
"{BC89EF96-8CEA-46FF-86C4-4CE0E7609802}",
|
|
8794
|
+
"Light Style 3 - Accent 1",
|
|
8795
|
+
5,
|
|
8796
|
+
"accent1"
|
|
8797
|
+
],
|
|
8798
|
+
[
|
|
8799
|
+
"{5DA37D80-6434-44D0-A028-1B22A696006F}",
|
|
8800
|
+
"Light Style 3 - Accent 2",
|
|
8801
|
+
5,
|
|
8802
|
+
"accent2"
|
|
8803
|
+
],
|
|
8804
|
+
[
|
|
8805
|
+
"{8799B23B-EC83-4686-B30A-512413B5E67A}",
|
|
8806
|
+
"Light Style 3 - Accent 3",
|
|
8807
|
+
5,
|
|
8808
|
+
"accent3"
|
|
8809
|
+
],
|
|
8810
|
+
[
|
|
8811
|
+
"{ED083AE6-46FA-4A59-8FB0-9F97EB10719F}",
|
|
8812
|
+
"Light Style 3 - Accent 4",
|
|
8813
|
+
5,
|
|
8814
|
+
"accent4"
|
|
8815
|
+
],
|
|
8816
|
+
[
|
|
8817
|
+
"{BDBED569-4797-4DF1-A0F4-6AAB3CD982D8}",
|
|
8818
|
+
"Light Style 3 - Accent 5",
|
|
8819
|
+
5,
|
|
8820
|
+
"accent5"
|
|
8821
|
+
],
|
|
8822
|
+
[
|
|
8823
|
+
"{E8B1032C-EA38-4F05-BA0D-38AFFFC7BED3}",
|
|
8824
|
+
"Light Style 3 - Accent 6",
|
|
8825
|
+
5,
|
|
8826
|
+
"accent6"
|
|
8827
|
+
],
|
|
8828
|
+
[
|
|
8829
|
+
"{793D81CF-94F2-401A-BA57-92F5A7B2D0C5}",
|
|
8830
|
+
"Medium Style 1",
|
|
8831
|
+
6,
|
|
8832
|
+
"dk1"
|
|
8833
|
+
],
|
|
8834
|
+
[
|
|
8835
|
+
"{B301B821-A1FF-4177-AEE7-76D212191A09}",
|
|
8836
|
+
"Medium Style 1 - Accent 1",
|
|
8837
|
+
6,
|
|
8838
|
+
"accent1"
|
|
8839
|
+
],
|
|
8840
|
+
[
|
|
8841
|
+
"{9DCAF9ED-07DC-4A11-8D7F-57B35C25682E}",
|
|
8842
|
+
"Medium Style 1 - Accent 2",
|
|
8843
|
+
6,
|
|
8844
|
+
"accent2"
|
|
8845
|
+
],
|
|
8846
|
+
[
|
|
8847
|
+
"{1FECB4D8-DB02-4DC6-A0A2-4F2EBAE1DC90}",
|
|
8848
|
+
"Medium Style 1 - Accent 3",
|
|
8849
|
+
6,
|
|
8850
|
+
"accent3"
|
|
8851
|
+
],
|
|
8852
|
+
[
|
|
8853
|
+
"{1E171933-4619-4E11-9A3F-F7608DF75F80}",
|
|
8854
|
+
"Medium Style 1 - Accent 4",
|
|
8855
|
+
6,
|
|
8856
|
+
"accent4"
|
|
8857
|
+
],
|
|
8858
|
+
[
|
|
8859
|
+
"{FABFCF23-3B69-468F-B69F-88F6DE6A72F2}",
|
|
8860
|
+
"Medium Style 1 - Accent 5",
|
|
8861
|
+
6,
|
|
8862
|
+
"accent5"
|
|
8863
|
+
],
|
|
8864
|
+
[
|
|
8865
|
+
"{10A1B5D5-9B99-4C35-A422-299274C87663}",
|
|
8866
|
+
"Medium Style 1 - Accent 6",
|
|
8867
|
+
6,
|
|
8868
|
+
"accent6"
|
|
8869
|
+
],
|
|
8870
|
+
[
|
|
8871
|
+
"{073A0DAA-6AF3-43AB-8588-CEC1D06C72B9}",
|
|
8872
|
+
"Medium Style 2",
|
|
8873
|
+
0,
|
|
8874
|
+
"dk1"
|
|
8875
|
+
],
|
|
8876
|
+
[
|
|
8877
|
+
"{21E4AEA4-8DFA-4A89-87EB-49C32662AFE0}",
|
|
8878
|
+
"Medium Style 2 - Accent 2",
|
|
8879
|
+
0,
|
|
8880
|
+
"accent2"
|
|
8881
|
+
],
|
|
8882
|
+
[
|
|
8883
|
+
"{F5AB1C69-6EDB-4FF4-983F-18BD219EF322}",
|
|
8884
|
+
"Medium Style 2 - Accent 3",
|
|
8885
|
+
0,
|
|
8886
|
+
"accent3"
|
|
8887
|
+
],
|
|
8888
|
+
[
|
|
8889
|
+
"{00A15C55-8517-42AA-B614-E9B94910E393}",
|
|
8890
|
+
"Medium Style 2 - Accent 4",
|
|
8891
|
+
0,
|
|
8892
|
+
"accent4"
|
|
8893
|
+
],
|
|
8894
|
+
[
|
|
8895
|
+
"{7DF18680-E054-41AD-8BC1-D1AEF772440D}",
|
|
8896
|
+
"Medium Style 2 - Accent 5",
|
|
8897
|
+
0,
|
|
8898
|
+
"accent5"
|
|
8899
|
+
],
|
|
8900
|
+
[
|
|
8901
|
+
"{93296810-A885-4BE3-A3E7-6D5BEEA58F35}",
|
|
8902
|
+
"Medium Style 2 - Accent 6",
|
|
8903
|
+
0,
|
|
8904
|
+
"accent6"
|
|
8905
|
+
],
|
|
8906
|
+
[
|
|
8907
|
+
"{8EC20E35-A176-4012-BC5E-935CFFF8708E}",
|
|
8908
|
+
"Medium Style 3",
|
|
8909
|
+
13
|
|
8910
|
+
],
|
|
8911
|
+
[
|
|
8912
|
+
"{6E25E649-3F16-4E02-A733-19D2CDBF48F0}",
|
|
8913
|
+
"Medium Style 3 - Accent 1",
|
|
8914
|
+
7,
|
|
8915
|
+
"accent1"
|
|
8916
|
+
],
|
|
8917
|
+
[
|
|
8918
|
+
"{85BE263C-DBD7-4A20-BB59-AAB30ACAA65A}",
|
|
8919
|
+
"Medium Style 3 - Accent 2",
|
|
8920
|
+
7,
|
|
8921
|
+
"accent2"
|
|
8922
|
+
],
|
|
8923
|
+
[
|
|
8924
|
+
"{EB344D84-9AFB-497E-A393-DC336BA19D2E}",
|
|
8925
|
+
"Medium Style 3 - Accent 3",
|
|
8926
|
+
7,
|
|
8927
|
+
"accent3"
|
|
8928
|
+
],
|
|
8929
|
+
[
|
|
8930
|
+
"{EB9631B5-78F2-41C9-869B-9F39066F8104}",
|
|
8931
|
+
"Medium Style 3 - Accent 4",
|
|
8932
|
+
7,
|
|
8933
|
+
"accent4"
|
|
8934
|
+
],
|
|
8935
|
+
[
|
|
8936
|
+
"{74C1A8A3-306A-4EB7-A6B1-4F7E0EB9C5D6}",
|
|
8937
|
+
"Medium Style 3 - Accent 5",
|
|
8938
|
+
7,
|
|
8939
|
+
"accent5"
|
|
8940
|
+
],
|
|
8941
|
+
[
|
|
8942
|
+
"{2A488322-F2BA-4B5B-9748-0D474271808F}",
|
|
8943
|
+
"Medium Style 3 - Accent 6",
|
|
8944
|
+
7,
|
|
8945
|
+
"accent6"
|
|
8946
|
+
],
|
|
8947
|
+
[
|
|
8948
|
+
"{D7AC3CCA-C797-4891-BE02-D94E43425B78}",
|
|
8949
|
+
"Medium Style 4",
|
|
8950
|
+
8,
|
|
8951
|
+
"dk1"
|
|
8952
|
+
],
|
|
8953
|
+
[
|
|
8954
|
+
"{69CF1AB2-1976-4502-BF36-3FF5EA218861}",
|
|
8955
|
+
"Medium Style 4 - Accent 1",
|
|
8956
|
+
8,
|
|
8957
|
+
"accent1"
|
|
8958
|
+
],
|
|
8959
|
+
[
|
|
8960
|
+
"{8A107856-5554-42FB-B03E-39F5DBC370BA}",
|
|
8961
|
+
"Medium Style 4 - Accent 2",
|
|
8962
|
+
8,
|
|
8963
|
+
"accent2"
|
|
8964
|
+
],
|
|
8965
|
+
[
|
|
8966
|
+
"{0505E3EF-67EA-436B-97B2-0124C06EBD24}",
|
|
8967
|
+
"Medium Style 4 - Accent 3",
|
|
8968
|
+
8,
|
|
8969
|
+
"accent3"
|
|
8970
|
+
],
|
|
8971
|
+
[
|
|
8972
|
+
"{C4B1156A-380E-4F78-BDF5-A606A8083BF9}",
|
|
8973
|
+
"Medium Style 4 - Accent 4",
|
|
8974
|
+
8,
|
|
8975
|
+
"accent4"
|
|
8976
|
+
],
|
|
8977
|
+
[
|
|
8978
|
+
"{22838BEF-8BB2-4498-84A7-C5851F593DF1}",
|
|
8979
|
+
"Medium Style 4 - Accent 5",
|
|
8980
|
+
8,
|
|
8981
|
+
"accent5"
|
|
8982
|
+
],
|
|
8983
|
+
[
|
|
8984
|
+
"{16D9F66E-5EB9-4882-86FB-DCBF35E3C3E4}",
|
|
8985
|
+
"Medium Style 4 - Accent 6",
|
|
8986
|
+
8,
|
|
8987
|
+
"accent6"
|
|
8988
|
+
],
|
|
8989
|
+
[
|
|
8990
|
+
"{E8034E78-7F5D-4C2E-B375-FC64B27BC917}",
|
|
8991
|
+
"Dark Style 1",
|
|
8992
|
+
14
|
|
8993
|
+
],
|
|
8994
|
+
[
|
|
8995
|
+
"{125E5076-3810-47DD-B79F-674D7AD40C01}",
|
|
8996
|
+
"Dark Style 1 - Accent 1",
|
|
8997
|
+
9,
|
|
8998
|
+
"accent1"
|
|
8999
|
+
],
|
|
9000
|
+
[
|
|
9001
|
+
"{37CE84F3-28C3-443E-9E96-99CF82512B78}",
|
|
9002
|
+
"Dark Style 1 - Accent 2",
|
|
9003
|
+
9,
|
|
9004
|
+
"accent2"
|
|
9005
|
+
],
|
|
9006
|
+
[
|
|
9007
|
+
"{D03447BB-5D67-496B-8E87-E561075AD55C}",
|
|
9008
|
+
"Dark Style 1 - Accent 3",
|
|
9009
|
+
9,
|
|
9010
|
+
"accent3"
|
|
9011
|
+
],
|
|
9012
|
+
[
|
|
9013
|
+
"{E929F9F4-4A8F-4326-A1B4-22849713DDAB}",
|
|
9014
|
+
"Dark Style 1 - Accent 4",
|
|
9015
|
+
9,
|
|
9016
|
+
"accent4"
|
|
9017
|
+
],
|
|
9018
|
+
[
|
|
9019
|
+
"{8FD4443E-F989-4FC4-A0C8-D5A2AF1F390B}",
|
|
9020
|
+
"Dark Style 1 - Accent 5",
|
|
9021
|
+
9,
|
|
9022
|
+
"accent5"
|
|
9023
|
+
],
|
|
9024
|
+
[
|
|
9025
|
+
"{AF606853-7671-496A-8E4F-DF71F8EC918B}",
|
|
9026
|
+
"Dark Style 1 - Accent 6",
|
|
9027
|
+
9,
|
|
9028
|
+
"accent6"
|
|
9029
|
+
],
|
|
9030
|
+
[
|
|
9031
|
+
"{5202B0CA-FC54-4496-8BCA-5EF66A818D29}",
|
|
9032
|
+
"Dark Style 2",
|
|
9033
|
+
15
|
|
9034
|
+
],
|
|
9035
|
+
[
|
|
9036
|
+
"{0660B408-B3CF-4A94-85FC-2B1E0A45F4A2}",
|
|
9037
|
+
"Dark Style 2 - Accent 1/Accent 2",
|
|
9038
|
+
10,
|
|
9039
|
+
"accent1",
|
|
9040
|
+
"accent2"
|
|
9041
|
+
],
|
|
9042
|
+
[
|
|
9043
|
+
"{91EBBBCC-DAD2-459C-BE2E-F6DE35CF9A28}",
|
|
9044
|
+
"Dark Style 2 - Accent 3/Accent 4",
|
|
9045
|
+
10,
|
|
9046
|
+
"accent3",
|
|
9047
|
+
"accent4"
|
|
9048
|
+
],
|
|
9049
|
+
[
|
|
9050
|
+
"{46F890A9-2807-4EBB-B81D-B2AA78EC7F39}",
|
|
9051
|
+
"Dark Style 2 - Accent 5/Accent 6",
|
|
9052
|
+
10,
|
|
9053
|
+
"accent5",
|
|
9054
|
+
"accent6"
|
|
9055
|
+
]
|
|
9056
|
+
];
|
|
9057
|
+
/**
|
|
9058
|
+
* The `a:tblStyle` element PowerPoint writes for the built-in style `styleId`, or `undefined`
|
|
9059
|
+
* when `styleId` is not one of the 74 built-in styles.
|
|
9060
|
+
*/
|
|
9061
|
+
function builtinTableStyleXml(styleId) {
|
|
9062
|
+
const row = STYLES.find((s) => s[0] === styleId);
|
|
9063
|
+
if (!row) return void 0;
|
|
9064
|
+
const [, styleName, index, ...args] = row;
|
|
9065
|
+
const body = BODIES[index]?.replace(/\$(\d)/g, (_, i) => args[Number(i)] ?? "") ?? "";
|
|
9066
|
+
return el("a:tblStyle", {
|
|
9067
|
+
styleId,
|
|
9068
|
+
styleName
|
|
9069
|
+
}, raw(body));
|
|
9070
|
+
}
|
|
9071
|
+
// src/package/parts/table.ts
|
|
9072
|
+
const tableContributor = {
|
|
9073
|
+
order: 40,
|
|
9074
|
+
parts: { tableStyles(pres) {
|
|
9075
|
+
const ids = /* @__PURE__ */ new Set();
|
|
9076
|
+
for (const slide of pres.slides) for (const obj of slide._slideObjects) if (obj._type === "table" && obj.options?.tableStyle) ids.add(obj.options.tableStyle);
|
|
9077
|
+
return [...ids.has(DEFAULT_TABLE_STYLE) ? /* @__PURE__ */ new Set([DEFAULT_TABLE_STYLE, ...ids]) : ids].flatMap((id) => builtinTableStyleXml(id) ?? []);
|
|
9078
|
+
} }
|
|
9079
|
+
};
|
|
9080
|
+
// src/families/table.ts
|
|
8508
9081
|
const tableFamily = {
|
|
8509
9082
|
name: "table",
|
|
8510
9083
|
authors: { addTable(slide, tableRows, options) {
|
|
8511
9084
|
const paged = addTableDefinition(slide, tableRows, options || {});
|
|
8512
9085
|
for (const made of paged) if (!slide._newAutoPagedSlides.includes(made)) slide._newAutoPagedSlides.push(made);
|
|
8513
9086
|
} },
|
|
8514
|
-
renderers: { ["table"]: renderTableObject }
|
|
9087
|
+
renderers: { ["table"]: renderTableObject },
|
|
9088
|
+
parts: tableContributor
|
|
8515
9089
|
};
|
|
8516
|
-
|
|
8517
|
-
//#region src/gen/slide/objects/zoom.ts
|
|
9090
|
+
// src/gen/slide/objects/zoom.ts
|
|
8518
9091
|
/** Zoom (Slide/Section/Summary) graphicData URI + `mc:Choice Requires` prefix + element local-names, per variant. */
|
|
8519
9092
|
const ZOOM_VARIANTS = {
|
|
8520
9093
|
slide: {
|
|
@@ -8541,7 +9114,7 @@ const P166_NS = "http://schemas.microsoft.com/office/powerpoint/2016/6/main";
|
|
|
8541
9114
|
/**
|
|
8542
9115
|
* The `p166:blipFill` + `p166:spPr` (preview image + framed tile) shared by a zoom tile's `zmPr`.
|
|
8543
9116
|
*
|
|
8544
|
-
* The same body `previewPicBody` builds for a `p:pic`, one namespace over
|
|
9117
|
+
* The same body `previewPicBody` builds for a `p:pic`, one namespace over, which is the only
|
|
8545
9118
|
* thing that ever differed between them.
|
|
8546
9119
|
*/
|
|
8547
9120
|
function zoomBlipSpPr(previewRid, xf) {
|
|
@@ -8559,7 +9132,7 @@ function zoomObjEl(variant, tile, returnToParent, transitionDur, localXf) {
|
|
|
8559
9132
|
zmAttrs["transitionDur"] = transitionDur;
|
|
8560
9133
|
return el(`${prefix}:${obj}`, objAttrs, raw(el(`${prefix}:zmPr`, zmAttrs, raw(zoomBlipSpPr(tile.previewRid, localXf)))));
|
|
8561
9134
|
}
|
|
8562
|
-
/** The `mc:Fallback` picture (or grouped pictures)
|
|
9135
|
+
/** The `mc:Fallback` picture (or grouped pictures): a hyperlinked thumbnail for pre-2016 consumers. */
|
|
8563
9136
|
function zoomFallbackPic(picId, objectName, tile, absXf) {
|
|
8564
9137
|
return el("p:pic", null, [raw(el("p:nvPicPr", null, [
|
|
8565
9138
|
raw(cNvPrEl(picId, objectName, "", voidEl("a:hlinkClick", {
|
|
@@ -8573,14 +9146,14 @@ function zoomFallbackPic(picId, objectName, tile, absXf) {
|
|
|
8573
9146
|
/**
|
|
8574
9147
|
* Render a `zoom` slide object to its `<mc:AlternateContent>` XML. The `mc:Choice` carries the real
|
|
8575
9148
|
* `<p:graphicFrame>` (Slide/Section/Summary Zoom in the 2016 zoom namespaces, read by PowerPoint
|
|
8576
|
-
* 2016+); the `mc:Fallback` carries a hyperlinked picture
|
|
9149
|
+
* 2016+); the `mc:Fallback` carries a hyperlinked picture (or, for a Summary Zoom, a group of them),
|
|
8577
9150
|
* so pre-2016 consumers still get a clickable navigation thumbnail. See `gen/define/zoom.ts`.
|
|
8578
9151
|
*/
|
|
8579
9152
|
function renderZoomObject(ctx) {
|
|
8580
9153
|
const { obj: slideItemObj, shapeId, frame: { x, y, cx, cy } } = ctx;
|
|
8581
9154
|
const zoom = slideItemObj.zoom;
|
|
8582
9155
|
if (!zoom) return "";
|
|
8583
|
-
const opts =
|
|
9156
|
+
const opts = ctx.itemOpts;
|
|
8584
9157
|
const objectName = opts.objectName;
|
|
8585
9158
|
const { uri, prefix, zm } = ZOOM_VARIANTS[zoom.variant];
|
|
8586
9159
|
const firstTile = zoom.tiles[0];
|
|
@@ -8660,8 +9233,7 @@ function renderZoomObject(ctx) {
|
|
|
8660
9233
|
fallback: fallbackInner
|
|
8661
9234
|
});
|
|
8662
9235
|
}
|
|
8663
|
-
|
|
8664
|
-
//#region src/gen/define/zoom.ts
|
|
9236
|
+
// src/gen/define/zoom.ts
|
|
8665
9237
|
const ZOOM_LABEL = {
|
|
8666
9238
|
slide: "Slide Zoom",
|
|
8667
9239
|
section: "Section Zoom",
|
|
@@ -8739,7 +9311,7 @@ function pushZoomObject(target, variant, options, zoom) {
|
|
|
8739
9311
|
};
|
|
8740
9312
|
target._slideObjects.push(newObject);
|
|
8741
9313
|
}
|
|
8742
|
-
/** Slide Zoom
|
|
9314
|
+
/** Slide Zoom: one tile linking to a single target slide. */
|
|
8743
9315
|
function addSlideZoomDefinition(target, opts) {
|
|
8744
9316
|
if (!opts?.target) {
|
|
8745
9317
|
warn("zoom/missing-target", "addSlideZoom requires a `target` slide (a Slide object or its 1-based number); ignoring.");
|
|
@@ -8768,7 +9340,7 @@ function addSlideZoomDefinition(target, opts) {
|
|
|
8768
9340
|
...settings
|
|
8769
9341
|
});
|
|
8770
9342
|
}
|
|
8771
|
-
/** Section Zoom
|
|
9343
|
+
/** Section Zoom: one tile linking to the start of a named section. */
|
|
8772
9344
|
function addSectionZoomDefinition(target, opts, sections) {
|
|
8773
9345
|
if (!opts?.sectionTitle) {
|
|
8774
9346
|
warn("zoom/missing-section-title", "addSectionZoom requires a `sectionTitle`; ignoring.");
|
|
@@ -8799,7 +9371,7 @@ function addSectionZoomDefinition(target, opts, sections) {
|
|
|
8799
9371
|
});
|
|
8800
9372
|
}
|
|
8801
9373
|
/**
|
|
8802
|
-
* Summary Zoom
|
|
9374
|
+
* Summary Zoom: a grid of tiles, one per section (excluding the host slide's own section).
|
|
8803
9375
|
* All tiles share the single placeholder/cover image; each links to its section's first slide.
|
|
8804
9376
|
*/
|
|
8805
9377
|
function addSummaryZoomDefinition(target, opts, sections) {
|
|
@@ -8856,8 +9428,7 @@ function addSummaryZoomDefinition(target, opts, sections) {
|
|
|
8856
9428
|
...settings
|
|
8857
9429
|
});
|
|
8858
9430
|
}
|
|
8859
|
-
|
|
8860
|
-
//#region src/families/zoom.ts
|
|
9431
|
+
// src/families/zoom.ts
|
|
8861
9432
|
const zoomFamily = {
|
|
8862
9433
|
name: "zoom",
|
|
8863
9434
|
authors: {
|
|
@@ -8873,7 +9444,6 @@ const zoomFamily = {
|
|
|
8873
9444
|
},
|
|
8874
9445
|
renderers: { ["zoom"]: renderZoomObject }
|
|
8875
9446
|
};
|
|
8876
|
-
|
|
8877
|
-
export { renderedSlideObjects as A, pushMediaRel as B, msMediaRid as C, findLayoutPlaceholder as D, placeholderOptionsForSlide as E, warnUnauthoredChild as F, SLIDE_METHOD_FAMILIES as I, composeFamilies as L, shapeIdCount as M, addChildDefinition as N, resolveTextAnchor as O, isGroupableObject as P, familyMethodUnavailable as R, alternateContentEl as S, addTextDefinition as T, resolveImageSource as V, chartPartNames as _, mediaFamily as a, GROUP_SHAPE_LOCK_ATTRS as b, commentsFamily as c, textFamily as d, shapeFamily as f, makeXmlCore as g, groupFamily as h, model3dFamily as i, resolveObjectNameToId as j, collectSlideShapeIds as k, chartFamily as l, imageFamily as m, tableFamily as n, measureFamily as o, notesFamily as p, oleFamily as r, connectorFamily as s, zoomFamily as t, animationsFamily as u, FMT_SCHEME_XML as v, previewRid as w, genXmlObjectLock as x, resolveImageExtent as y, requirePresentationAuthor as z };
|
|
9447
|
+
export { statedPlaceholderBinding as A, composeFamilies as B, msMediaRid as C, checkPlaceholderBinding as D, placeholderOptionsForSlide as E, shapeIdCount as F, requirePresentationAuthor as H, addChildDefinition as I, isGroupableObject as L, collectSlideShapeIds as M, renderedSlideObjects as N, findLayoutPlaceholder as O, resolveObjectNameToId as P, warnUnauthoredChild as R, alternateContentEl as S, addTextDefinition as T, pushMediaRel as U, familyMethodUnavailable as V, resolveImageSource as W, makeXmlCore as _, mediaFamily as a, resolveImageExtent as b, commentsFamily as c, textFamily as d, shapeFamily as f, makeXmlTableStyles as g, groupFamily as h, model3dFamily as i, resolveTextAnchor as j, layoutPlaceholderName as k, chartFamily as l, imageFamily as m, tableFamily as n, measureFamily as o, notesFamily as p, oleFamily as r, connectorFamily as s, zoomFamily as t, animationsFamily as u, chartPartNames as v, previewRid as w, genXmlObjectLock as x, FMT_SCHEME_XML as y, SLIDE_METHOD_FAMILIES as z };
|
|
8878
9448
|
|
|
8879
|
-
//# sourceMappingURL=zoom-
|
|
9449
|
+
//# sourceMappingURL=zoom-CSSeOwM8.js.map
|