pptx-glimpse 3.1.1 → 3.2.1

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.
@@ -4317,6 +4317,16 @@ var EDIT_KIND_DESCRIPTORS = {
4317
4317
  insertedSlidePartPath: () => void 0,
4318
4318
  insertedShape: () => void 0
4319
4319
  },
4320
+ updateParagraphProperties: {
4321
+ reservedPartPaths: () => [],
4322
+ dirtyPartPath: (edit) => edit.handle.partPath,
4323
+ targetsShape: (edit, shapeHandle) => edit.handle.partPath === shapeHandle.partPath && paragraphShapeId(edit.handle) === shapeHandle.nodeId,
4324
+ invalidatingPartPaths: (edit) => [edit.handle.partPath],
4325
+ reservedShapeId: () => void 0,
4326
+ slideTopologyOperation: () => void 0,
4327
+ insertedSlidePartPath: () => void 0,
4328
+ insertedShape: () => void 0
4329
+ },
4320
4330
  replaceParagraphPlainText: {
4321
4331
  reservedPartPaths: () => [],
4322
4332
  dirtyPartPath: (edit) => edit.handle.partPath,
@@ -4337,6 +4347,26 @@ var EDIT_KIND_DESCRIPTORS = {
4337
4347
  insertedSlidePartPath: () => void 0,
4338
4348
  insertedShape: () => void 0
4339
4349
  },
4350
+ updateShapeFill: {
4351
+ reservedPartPaths: () => [],
4352
+ dirtyPartPath: (edit) => edit.handle.partPath,
4353
+ targetsShape: (edit, shapeHandle) => sourceHandlesEqual(edit.handle, shapeHandle),
4354
+ invalidatingPartPaths: (edit) => [edit.handle.partPath],
4355
+ reservedShapeId: () => void 0,
4356
+ slideTopologyOperation: () => void 0,
4357
+ insertedSlidePartPath: () => void 0,
4358
+ insertedShape: () => void 0
4359
+ },
4360
+ updateShapeOutline: {
4361
+ reservedPartPaths: () => [],
4362
+ dirtyPartPath: (edit) => edit.handle.partPath,
4363
+ targetsShape: (edit, shapeHandle) => sourceHandlesEqual(edit.handle, shapeHandle),
4364
+ invalidatingPartPaths: (edit) => [edit.handle.partPath],
4365
+ reservedShapeId: () => void 0,
4366
+ slideTopologyOperation: () => void 0,
4367
+ insertedSlidePartPath: () => void 0,
4368
+ insertedShape: () => void 0
4369
+ },
4340
4370
  addTextBox: {
4341
4371
  reservedPartPaths: (edit) => [edit.slidePartPath],
4342
4372
  dirtyPartPath: (edit) => edit.slidePartPath,
@@ -4406,6 +4436,20 @@ var EDIT_KIND_DESCRIPTORS = {
4406
4436
  insertedSlidePartPath: (edit) => edit.newSlidePartPath,
4407
4437
  insertedShape: () => void 0
4408
4438
  },
4439
+ moveSlide: {
4440
+ reservedPartPaths: (edit) => [edit.slidePartPath],
4441
+ dirtyPartPath: () => void 0,
4442
+ targetsShape: () => false,
4443
+ invalidatingPartPaths: (edit) => [edit.slidePartPath],
4444
+ reservedShapeId: () => void 0,
4445
+ slideTopologyOperation: (edit) => ({
4446
+ kind: "moveSlide",
4447
+ relationshipId: edit.relationshipId,
4448
+ toIndex: edit.toIndex
4449
+ }),
4450
+ insertedSlidePartPath: () => void 0,
4451
+ insertedShape: () => void 0
4452
+ },
4409
4453
  deleteSlide: {
4410
4454
  reservedPartPaths: (edit) => [edit.slidePartPath],
4411
4455
  dirtyPartPath: () => void 0,
@@ -5043,129 +5087,560 @@ function parseEnumValue(value, allowed) {
5043
5087
  function parseEnumValueWithDefault(value, allowed, fallback) {
5044
5088
  return parseEnumValue(value, allowed) ?? fallback;
5045
5089
  }
5046
- var KNOWN_TXBODY_CHILDREN = /* @__PURE__ */ new Set(["bodyPr", "lstStyle", "p"]);
5047
- var KNOWN_PARAGRAPH_CHILDREN = /* @__PURE__ */ new Set([
5048
- "pPr",
5090
+ var RECTANGLE_ALIGNMENT_TOKENS = /* @__PURE__ */ new Set([
5091
+ "tl",
5092
+ "t",
5093
+ "tr",
5094
+ "l",
5095
+ "ctr",
5049
5096
  "r",
5050
- "fld",
5051
- "br",
5052
- "endParaRPr"
5097
+ "bl",
5098
+ "b",
5099
+ "br"
5053
5100
  ]);
5054
- var KNOWN_RUN_CHILDREN = /* @__PURE__ */ new Set(["rPr", "t"]);
5055
- var KNOWN_RUN_PROPERTY_CHILDREN = /* @__PURE__ */ new Set([
5056
- "latin",
5057
- "ea",
5058
- "cs",
5059
- "solidFill"
5101
+ var COLOR_TRANSFORM_KINDS = /* @__PURE__ */ new Set([
5102
+ "lumMod",
5103
+ "lumOff",
5104
+ "tint",
5105
+ "shade",
5106
+ "alpha"
5060
5107
  ]);
5061
- var ALIGN_MAP = {
5062
- l: "left",
5063
- ctr: "center",
5064
- r: "right",
5065
- just: "justify"
5066
- };
5067
- var ANCHOR_MAP = {
5068
- t: "top",
5069
- ctr: "middle",
5070
- b: "bottom"
5108
+ var RAW_FILL_LOCAL_NAMES = ["grpFill"];
5109
+ var PRESET_COLOR_HEX = {
5110
+ black: "000000",
5111
+ white: "FFFFFF",
5112
+ red: "FF0000",
5113
+ green: "008000",
5114
+ blue: "0000FF",
5115
+ yellow: "FFFF00",
5116
+ cyan: "00FFFF",
5117
+ magenta: "FF00FF"
5071
5118
  };
5072
- var WRAP_VALUES = /* @__PURE__ */ new Set(["square", "none"]);
5073
- var VERTICAL_VALUES = /* @__PURE__ */ new Set([
5074
- "horz",
5075
- "vert",
5076
- "vert270",
5077
- "eaVert",
5078
- "wordArtVert",
5079
- "mongolianVert"
5080
- ]);
5081
- var VALID_AUTO_NUM_SCHEMES = /* @__PURE__ */ new Set([
5082
- "arabicPeriod",
5083
- "arabicParenR",
5084
- "romanUcPeriod",
5085
- "romanLcPeriod",
5086
- "alphaUcPeriod",
5087
- "alphaLcPeriod",
5088
- "alphaLcParenR",
5089
- "alphaUcParenR",
5090
- "arabicPlain"
5091
- ]);
5092
- function parseTextBody(txBody, partPath, nextId, ownerNodeId, ownerOrderingSlot, orderedTxBody) {
5093
- if (!txBody) return void 0;
5094
- const properties = parseBodyProperties(getChild(txBody, "bodyPr"));
5095
- const listStyle = parseTextStyle(getChild(txBody, "lstStyle"));
5096
- const orderedParagraphs = orderedTxBody?.filter((child) => orderedLocalName(child) === "p").map((child) => {
5097
- const key = orderedKey(child);
5098
- const value = key !== void 0 ? child[key] : void 0;
5099
- return Array.isArray(value) ? value : void 0;
5100
- });
5101
- const paragraphs = [];
5102
- let logicalParagraphIndex = 0;
5103
- getChildArray(txBody, "p").forEach((p, paragraphIndex) => {
5104
- const orderedChildren = orderedParagraphs?.[paragraphIndex];
5105
- if (orderedChildren !== void 0 && hasMultipleBulletPPr(p, orderedChildren)) {
5106
- const split = splitInterleavedParagraph(
5107
- p,
5108
- orderedChildren,
5109
- partPath,
5110
- nextId,
5111
- ownerNodeId,
5112
- ownerOrderingSlot,
5113
- logicalParagraphIndex
5119
+ function parseColorElement(parent) {
5120
+ if (!parent) return void 0;
5121
+ const srgb = getChild(parent, "srgbClr");
5122
+ if (srgb) {
5123
+ const hex = getAttr(srgb, "val");
5124
+ if (hex !== void 0) {
5125
+ return withTransforms({ kind: "srgb", hex: hex.toUpperCase() }, srgb);
5126
+ }
5127
+ }
5128
+ const scheme = getChild(parent, "schemeClr");
5129
+ if (scheme) {
5130
+ const name = getAttr(scheme, "val");
5131
+ if (name !== void 0) {
5132
+ return withTransforms({ kind: "scheme", scheme: name }, scheme);
5133
+ }
5134
+ }
5135
+ const sys = getChild(parent, "sysClr");
5136
+ if (sys) {
5137
+ const val = getAttr(sys, "val");
5138
+ if (val !== void 0) {
5139
+ const lastClr = getAttr(sys, "lastClr");
5140
+ return withTransforms(
5141
+ {
5142
+ kind: "system",
5143
+ value: val,
5144
+ ...lastClr !== void 0 ? { lastColor: lastClr.toUpperCase() } : {}
5145
+ },
5146
+ sys
5114
5147
  );
5115
- paragraphs.push(...split);
5116
- logicalParagraphIndex += split.length;
5117
- return;
5118
5148
  }
5119
- paragraphs.push(
5120
- parseParagraph(
5121
- p,
5122
- partPath,
5123
- nextId,
5124
- ownerNodeId,
5125
- ownerOrderingSlot,
5126
- logicalParagraphIndex,
5127
- orderedChildren
5128
- )
5129
- );
5130
- logicalParagraphIndex++;
5131
- });
5132
- const rawSidecars = collectUnknownSidecars(txBody, KNOWN_TXBODY_CHILDREN, nextId);
5133
- return {
5134
- paragraphs,
5135
- ...properties !== void 0 ? { properties } : {},
5136
- ...listStyle !== void 0 ? { listStyle } : {},
5137
- handle: { partPath },
5138
- ...rawSidecars.length > 0 ? { rawSidecars } : {}
5149
+ }
5150
+ return void 0;
5151
+ }
5152
+ function parseEffectList(effectList) {
5153
+ if (effectList === void 0) return void 0;
5154
+ const outerShadow = parseOuterShadow(getChild(effectList, "outerShdw"));
5155
+ const innerShadow = parseInnerShadow(getChild(effectList, "innerShdw"));
5156
+ const glow = parseGlow(getChild(effectList, "glow"));
5157
+ const softEdge = parseSoftEdge(getChild(effectList, "softEdge"));
5158
+ const parsed = {
5159
+ ...outerShadow !== void 0 ? { outerShadow } : {},
5160
+ ...innerShadow !== void 0 ? { innerShadow } : {},
5161
+ ...glow !== void 0 ? { glow } : {},
5162
+ ...softEdge !== void 0 ? { softEdge } : {}
5163
+ };
5164
+ return Object.keys(parsed).length > 0 ? parsed : void 0;
5165
+ }
5166
+ function parseBlipEffects(blip) {
5167
+ if (blip === void 0) return void 0;
5168
+ const grayscale = getChild(blip, "grayscl") !== void 0;
5169
+ const biLevel = parseBiLevel(getChild(blip, "biLevel"));
5170
+ const blur = parseBlurEffect(getChild(blip, "blur"));
5171
+ const lum = parseLumEffect(getChild(blip, "lum"));
5172
+ const duotone = parseDuotoneEffect(getChild(blip, "duotone"));
5173
+ const clrChange = parseColorChangeEffect(getChild(blip, "clrChange"));
5174
+ const parsed = {
5175
+ grayscale,
5176
+ ...biLevel !== void 0 ? { biLevel } : {},
5177
+ ...blur !== void 0 ? { blur } : {},
5178
+ ...lum !== void 0 ? { lum } : {},
5179
+ ...duotone !== void 0 ? { duotone } : {},
5180
+ ...clrChange !== void 0 ? { clrChange } : {}
5139
5181
  };
5182
+ return grayscale || biLevel !== void 0 || blur !== void 0 || lum !== void 0 || duotone !== void 0 || clrChange !== void 0 ? parsed : void 0;
5140
5183
  }
5141
- function parseTextStyle(node) {
5184
+ function parseOuterShadow(node) {
5142
5185
  if (node === void 0) return void 0;
5143
- const defaultParagraph = parseParagraphProperties(getChild(node, "defPPr"));
5144
- const levels = Array.from(
5145
- { length: 9 },
5146
- (_, index) => parseParagraphProperties(getChild(node, `lvl${index + 1}pPr`))
5147
- );
5148
- if (defaultParagraph === void 0 && levels.every((level) => level === void 0)) {
5149
- return void 0;
5150
- }
5151
- return { ...defaultParagraph !== void 0 ? { defaultParagraph } : {}, levels };
5186
+ const color = parseColorElement(node);
5187
+ if (color === void 0) return void 0;
5188
+ return {
5189
+ blurRadius: asEmu2(numericAttr2(node, "blurRad") ?? 0),
5190
+ distance: asEmu2(numericAttr2(node, "dist") ?? 0),
5191
+ direction: asOoxmlAngle(numericAttr2(node, "dir") ?? 0),
5192
+ color,
5193
+ alignment: parseRectangleAlignment(getAttr(node, "algn"), "b"),
5194
+ rotateWithShape: getAttr(node, "rotWithShape") !== "0"
5195
+ };
5152
5196
  }
5153
- function hasMultipleBulletPPr(p, orderedChildren) {
5154
- const pPrList = getChildArray(p, "pPr");
5155
- let bulletPPrCount = 0;
5156
- let pPrCounter = 0;
5157
- for (const child of orderedChildren) {
5158
- if (orderedLocalName(child) !== "pPr") continue;
5159
- const pPr = pPrList[pPrCounter];
5160
- if (pPr !== void 0 && (getChild(pPr, "buChar") !== void 0 || getChild(pPr, "buAutoNum") !== void 0)) {
5161
- bulletPPrCount++;
5162
- if (bulletPPrCount >= 2) return true;
5163
- }
5164
- pPrCounter++;
5165
- }
5166
- return false;
5197
+ function parseInnerShadow(node) {
5198
+ if (node === void 0) return void 0;
5199
+ const color = parseColorElement(node);
5200
+ if (color === void 0) return void 0;
5201
+ return {
5202
+ blurRadius: asEmu2(numericAttr2(node, "blurRad") ?? 0),
5203
+ distance: asEmu2(numericAttr2(node, "dist") ?? 0),
5204
+ direction: asOoxmlAngle(numericAttr2(node, "dir") ?? 0),
5205
+ color
5206
+ };
5167
5207
  }
5168
- function splitInterleavedParagraph(p, orderedChildren, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex) {
5208
+ function parseGlow(node) {
5209
+ if (node === void 0) return void 0;
5210
+ const color = parseColorElement(node);
5211
+ if (color === void 0) return void 0;
5212
+ return {
5213
+ radius: asEmu2(numericAttr2(node, "rad") ?? 0),
5214
+ color
5215
+ };
5216
+ }
5217
+ function parseSoftEdge(node) {
5218
+ if (node === void 0) return void 0;
5219
+ return {
5220
+ radius: asEmu2(numericAttr2(node, "rad") ?? 0)
5221
+ };
5222
+ }
5223
+ function parseBiLevel(node) {
5224
+ if (node === void 0) return void 0;
5225
+ return {
5226
+ threshold: (numericAttr2(node, "thresh") ?? 5e4) / 1e5
5227
+ };
5228
+ }
5229
+ function parseBlurEffect(node) {
5230
+ if (node === void 0) return void 0;
5231
+ return {
5232
+ radius: asEmu2(numericAttr2(node, "rad") ?? 0),
5233
+ grow: getAttr(node, "grow") !== "0"
5234
+ };
5235
+ }
5236
+ function parseLumEffect(node) {
5237
+ if (node === void 0) return void 0;
5238
+ return {
5239
+ brightness: (numericAttr2(node, "bright") ?? 0) / 1e5,
5240
+ contrast: (numericAttr2(node, "contrast") ?? 0) / 1e5
5241
+ };
5242
+ }
5243
+ function parseDuotoneEffect(node) {
5244
+ if (node === void 0) return void 0;
5245
+ const colors = collectColorChildren(node);
5246
+ if (colors.length < 2) return void 0;
5247
+ return { color1: colors[0], color2: colors[1] };
5248
+ }
5249
+ function parseColorChangeEffect(node) {
5250
+ if (node === void 0) return void 0;
5251
+ const from = firstColorChild(getChild(node, "clrFrom"));
5252
+ const to = firstColorChild(getChild(node, "clrTo"));
5253
+ return from !== void 0 && to !== void 0 ? { from, to } : void 0;
5254
+ }
5255
+ function collectColorChildren(parent) {
5256
+ const colors = [];
5257
+ for (const [key, value] of Object.entries(parent)) {
5258
+ if (key.startsWith("@_")) continue;
5259
+ const nodes = Array.isArray(value) ? value : [value];
5260
+ for (const node of nodes) {
5261
+ if (!isXmlNode(node)) continue;
5262
+ const color = parseColorChild(key, node);
5263
+ if (color !== void 0) colors.push(color);
5264
+ }
5265
+ }
5266
+ return colors;
5267
+ }
5268
+ function firstColorChild(parent) {
5269
+ return parent !== void 0 ? collectColorChildren(parent)[0] : void 0;
5270
+ }
5271
+ function parseColorChild(key, node) {
5272
+ const name = localName(key);
5273
+ return name === "prstClr" ? parsePresetColor(node) : parseColorElement({ [name]: node });
5274
+ }
5275
+ function isXmlNode(value) {
5276
+ return typeof value === "object" && value !== null;
5277
+ }
5278
+ function parsePresetColor(node) {
5279
+ const value = getAttr(node, "val");
5280
+ const hex = value !== void 0 ? PRESET_COLOR_HEX[value] : void 0;
5281
+ return hex !== void 0 ? withTransforms({ kind: "srgb", hex }, node) : void 0;
5282
+ }
5283
+ function parseFill(parent, nextId) {
5284
+ if (!parent) return void 0;
5285
+ const solid = getChild(parent, "solidFill");
5286
+ if (solid) {
5287
+ const color = parseColorElement(solid);
5288
+ if (color) return { kind: "solid", color };
5289
+ return { kind: "raw", raw: makeSidecar("a:solidFill", solid, nextId) };
5290
+ }
5291
+ if (hasChild(parent, "noFill")) return { kind: "none" };
5292
+ const grad = getChild(parent, "gradFill");
5293
+ if (grad) {
5294
+ const fill = parseGradientFill(grad);
5295
+ return fill ?? { kind: "raw", raw: makeSidecar("a:gradFill", grad, nextId) };
5296
+ }
5297
+ const blip = getChild(parent, "blipFill");
5298
+ if (blip) {
5299
+ return parseBlipFill(blip) ?? { kind: "raw", raw: makeSidecar("a:blipFill", blip, nextId) };
5300
+ }
5301
+ const pattern = getChild(parent, "pattFill");
5302
+ if (pattern) {
5303
+ const fill = parsePatternFill(pattern);
5304
+ return fill ?? { kind: "raw", raw: makeSidecar("a:pattFill", pattern, nextId) };
5305
+ }
5306
+ for (const name of RAW_FILL_LOCAL_NAMES) {
5307
+ if (hasChild(parent, name)) {
5308
+ return { kind: "raw", raw: makeSidecar(`a:${name}`, getChild(parent, name) ?? {}, nextId) };
5309
+ }
5310
+ }
5311
+ return void 0;
5312
+ }
5313
+ function parseGradientFill(grad) {
5314
+ const stops = [];
5315
+ for (const gs of getChildArray(getChild(grad, "gsLst"), "gs")) {
5316
+ const color = parseColorElement(gs);
5317
+ if (color === void 0) continue;
5318
+ stops.push({
5319
+ position: (numericAttr2(gs, "pos") ?? 0) / 1e5,
5320
+ color
5321
+ });
5322
+ }
5323
+ if (stops.length === 0) return void 0;
5324
+ const path = getChild(grad, "path");
5325
+ if (path !== void 0) {
5326
+ const fillToRect = getChild(path, "fillToRect");
5327
+ const l = numericAttr2(fillToRect, "l") ?? 0;
5328
+ const t = numericAttr2(fillToRect, "t") ?? 0;
5329
+ const r = numericAttr2(fillToRect, "r") ?? 0;
5330
+ const b = numericAttr2(fillToRect, "b") ?? 0;
5331
+ return {
5332
+ kind: "gradient",
5333
+ gradientType: "radial",
5334
+ stops,
5335
+ centerX: (l + (1e5 - r)) / 2 / 1e5,
5336
+ centerY: (t + (1e5 - b)) / 2 / 1e5
5337
+ };
5338
+ }
5339
+ return {
5340
+ kind: "gradient",
5341
+ gradientType: "linear",
5342
+ stops,
5343
+ angle: asOoxmlAngle(numericAttr2(getChild(grad, "lin"), "ang") ?? 0)
5344
+ };
5345
+ }
5346
+ function parseBlipFill(blipFill) {
5347
+ const blip = getChild(blipFill, "blip");
5348
+ const embed = getNamespacedAttr(blip, "embed");
5349
+ if (embed === void 0) return void 0;
5350
+ const tile = parseImageFillTile(getChild(blipFill, "tile"));
5351
+ return {
5352
+ kind: "image",
5353
+ blipRelationshipId: asRelationshipId(embed),
5354
+ ...tile !== void 0 ? { tile } : {}
5355
+ };
5356
+ }
5357
+ function parseImageFillTile(tile) {
5358
+ if (tile === void 0) return void 0;
5359
+ const flip = getAttr(tile, "flip") ?? "none";
5360
+ return {
5361
+ tx: asEmu2(numericAttr2(tile, "tx") ?? 0),
5362
+ ty: asEmu2(numericAttr2(tile, "ty") ?? 0),
5363
+ sx: (numericAttr2(tile, "sx") ?? 1e5) / 1e5,
5364
+ sy: (numericAttr2(tile, "sy") ?? 1e5) / 1e5,
5365
+ flip: flip === "x" || flip === "y" || flip === "xy" ? flip : "none",
5366
+ align: parseRectangleAlignment(getAttr(tile, "algn"), "tl")
5367
+ };
5368
+ }
5369
+ function parseRectangleAlignment(value, fallback) {
5370
+ return parseEnumValueWithDefault(value, RECTANGLE_ALIGNMENT_TOKENS, fallback);
5371
+ }
5372
+ function parsePatternFill(pattern) {
5373
+ const foregroundColor = parseColorElement(getChild(pattern, "fgClr"));
5374
+ const backgroundColor = parseColorElement(getChild(pattern, "bgClr"));
5375
+ if (foregroundColor === void 0 || backgroundColor === void 0) return void 0;
5376
+ return {
5377
+ kind: "pattern",
5378
+ preset: getAttr(pattern, "prst") ?? "ltDnDiag",
5379
+ foregroundColor,
5380
+ backgroundColor
5381
+ };
5382
+ }
5383
+ function parseOutline(spPr, nextId) {
5384
+ const ln = getChild(spPr, "ln");
5385
+ return parseLine(ln, nextId);
5386
+ }
5387
+ function parseLine(ln, nextId) {
5388
+ if (!ln) return void 0;
5389
+ const width = numericAttr2(ln, "w");
5390
+ const fill = parseFill(ln, nextId);
5391
+ const dashStyle = parseDashStyle(getChild(ln, "prstDash"));
5392
+ const customDash = parseCustomDash(ln);
5393
+ const lineCap = parseLineCap(getAttr(ln, "cap"));
5394
+ const lineJoin = parseLineJoin(ln);
5395
+ const headEnd = parseArrowEndpoint(getChild(ln, "headEnd"));
5396
+ const tailEnd = parseArrowEndpoint(getChild(ln, "tailEnd"));
5397
+ return {
5398
+ ...width !== void 0 ? { width: asEmu2(width) } : {},
5399
+ ...fill !== void 0 ? { fill } : {},
5400
+ ...dashStyle !== void 0 ? { dashStyle } : {},
5401
+ ...customDash !== void 0 ? { customDash } : {},
5402
+ ...lineCap !== void 0 ? { lineCap } : {},
5403
+ ...lineJoin !== void 0 ? { lineJoin } : {},
5404
+ ...headEnd !== void 0 ? { headEnd } : {},
5405
+ ...tailEnd !== void 0 ? { tailEnd } : {}
5406
+ };
5407
+ }
5408
+ function parseTransform(spPr) {
5409
+ const xfrm = getChild(spPr, "xfrm");
5410
+ if (!xfrm) return void 0;
5411
+ const off = getChild(xfrm, "off");
5412
+ const ext = getChild(xfrm, "ext");
5413
+ const offsetX = numericAttr2(off, "x");
5414
+ const offsetY = numericAttr2(off, "y");
5415
+ const width = numericAttr2(ext, "cx");
5416
+ const height = numericAttr2(ext, "cy");
5417
+ if (offsetX === void 0 || offsetY === void 0 || width === void 0 || height === void 0) {
5418
+ return void 0;
5419
+ }
5420
+ const rotation = numericAttr2(xfrm, "rot");
5421
+ const flipH = getAttr(xfrm, "flipH");
5422
+ const flipV = getAttr(xfrm, "flipV");
5423
+ return {
5424
+ offsetX: asEmu2(offsetX),
5425
+ offsetY: asEmu2(offsetY),
5426
+ width: asEmu2(width),
5427
+ height: asEmu2(height),
5428
+ ...rotation !== void 0 ? { rotation: asOoxmlAngle(rotation) } : {},
5429
+ ...isTrue(flipH) ? { flipHorizontal: true } : {},
5430
+ ...isTrue(flipV) ? { flipVertical: true } : {}
5431
+ };
5432
+ }
5433
+ function withTransforms(base, colorNode) {
5434
+ const transforms = [];
5435
+ for (const key of Object.keys(colorNode)) {
5436
+ if (key.startsWith("@_")) continue;
5437
+ const kind = localName(key);
5438
+ const transformKind = parseEnumValue(kind, COLOR_TRANSFORM_KINDS);
5439
+ if (transformKind === void 0) continue;
5440
+ const value = colorNode[key];
5441
+ const items = Array.isArray(value) ? value : [value];
5442
+ for (const item of items) {
5443
+ const raw = getAttr(unsafeOoxmlBoundaryAssertion(item), "val");
5444
+ if (raw === void 0) continue;
5445
+ const numeric = Number(raw);
5446
+ if (!Number.isFinite(numeric)) continue;
5447
+ transforms.push({
5448
+ kind: transformKind,
5449
+ value: asOoxmlPercent(numeric)
5450
+ });
5451
+ }
5452
+ }
5453
+ return transforms.length > 0 ? { ...base, transforms } : base;
5454
+ }
5455
+ function numericAttr2(node, name) {
5456
+ const raw = getAttr(node, name);
5457
+ if (raw === void 0) return void 0;
5458
+ const value = Number(raw);
5459
+ return Number.isFinite(value) ? value : void 0;
5460
+ }
5461
+ function isTrue(value) {
5462
+ return value === "1" || value === "true";
5463
+ }
5464
+ function parseDashStyle(prstDash) {
5465
+ const value = getAttr(prstDash, "val");
5466
+ return parseEnumValue(value, DASH_STYLES);
5467
+ }
5468
+ function parseCustomDash(ln) {
5469
+ const custDash = getChild(ln, "custDash");
5470
+ const segments = getChildArray(custDash, "ds");
5471
+ if (segments.length === 0) return void 0;
5472
+ return segments.flatMap((segment) => [
5473
+ (numericAttr2(segment, "d") ?? 1e5) / 1e5,
5474
+ (numericAttr2(segment, "sp") ?? 1e5) / 1e5
5475
+ ]);
5476
+ }
5477
+ var LINE_CAP_MAP = {
5478
+ flat: "butt",
5479
+ sq: "square",
5480
+ rnd: "round"
5481
+ };
5482
+ function parseLineCap(value) {
5483
+ return value !== void 0 ? LINE_CAP_MAP[value] : void 0;
5484
+ }
5485
+ function parseLineJoin(ln) {
5486
+ if (hasChild(ln, "round")) return "round";
5487
+ if (hasChild(ln, "bevel")) return "bevel";
5488
+ if (hasChild(ln, "miter")) return "miter";
5489
+ return void 0;
5490
+ }
5491
+ function parseArrowEndpoint(node) {
5492
+ if (!node) return void 0;
5493
+ const type = parseEnumValue(getAttr(node, "type"), ARROW_TYPES);
5494
+ if (type === void 0) return void 0;
5495
+ const width = getAttr(node, "w") ?? "med";
5496
+ const length = getAttr(node, "len") ?? "med";
5497
+ return {
5498
+ type,
5499
+ width: parseEnumValueWithDefault(width, ARROW_SIZES, "med"),
5500
+ length: parseEnumValueWithDefault(length, ARROW_SIZES, "med")
5501
+ };
5502
+ }
5503
+ var DASH_STYLES = /* @__PURE__ */ new Set([
5504
+ "solid",
5505
+ "dash",
5506
+ "dot",
5507
+ "dashDot",
5508
+ "lgDash",
5509
+ "lgDashDot",
5510
+ "sysDash",
5511
+ "sysDot"
5512
+ ]);
5513
+ var ARROW_TYPES = /* @__PURE__ */ new Set([
5514
+ "triangle",
5515
+ "stealth",
5516
+ "diamond",
5517
+ "oval",
5518
+ "arrow"
5519
+ ]);
5520
+ var ARROW_SIZES = /* @__PURE__ */ new Set(["sm", "med", "lg"]);
5521
+ var KNOWN_TXBODY_CHILDREN = /* @__PURE__ */ new Set(["bodyPr", "lstStyle", "p"]);
5522
+ var KNOWN_PARAGRAPH_CHILDREN = /* @__PURE__ */ new Set([
5523
+ "pPr",
5524
+ "r",
5525
+ "fld",
5526
+ "br",
5527
+ "endParaRPr"
5528
+ ]);
5529
+ var KNOWN_RUN_CHILDREN = /* @__PURE__ */ new Set(["rPr", "t"]);
5530
+ var KNOWN_RUN_PROPERTY_CHILDREN = /* @__PURE__ */ new Set([
5531
+ "latin",
5532
+ "ea",
5533
+ "cs",
5534
+ "solidFill"
5535
+ ]);
5536
+ var ALIGN_MAP = {
5537
+ l: "left",
5538
+ ctr: "center",
5539
+ r: "right",
5540
+ just: "justify"
5541
+ };
5542
+ var ANCHOR_MAP = {
5543
+ t: "top",
5544
+ ctr: "middle",
5545
+ b: "bottom"
5546
+ };
5547
+ var WRAP_VALUES = /* @__PURE__ */ new Set(["square", "none"]);
5548
+ var VERTICAL_VALUES = /* @__PURE__ */ new Set([
5549
+ "horz",
5550
+ "vert",
5551
+ "vert270",
5552
+ "eaVert",
5553
+ "wordArtVert",
5554
+ "mongolianVert"
5555
+ ]);
5556
+ var VALID_AUTO_NUM_SCHEMES = /* @__PURE__ */ new Set([
5557
+ "arabicPeriod",
5558
+ "arabicParenR",
5559
+ "romanUcPeriod",
5560
+ "romanLcPeriod",
5561
+ "alphaUcPeriod",
5562
+ "alphaLcPeriod",
5563
+ "alphaLcParenR",
5564
+ "alphaUcParenR",
5565
+ "arabicPlain"
5566
+ ]);
5567
+ function parseTextBody(txBody, partPath, nextId, ownerNodeId, ownerOrderingSlot, orderedTxBody) {
5568
+ if (!txBody) return void 0;
5569
+ const properties = parseBodyProperties(getChild(txBody, "bodyPr"));
5570
+ const listStyle = parseTextStyle(getChild(txBody, "lstStyle"));
5571
+ const orderedParagraphs = orderedTxBody?.filter((child) => orderedLocalName(child) === "p").map((child) => {
5572
+ const key = orderedKey(child);
5573
+ const value = key !== void 0 ? child[key] : void 0;
5574
+ return Array.isArray(value) ? value : void 0;
5575
+ });
5576
+ const paragraphs = [];
5577
+ let logicalParagraphIndex = 0;
5578
+ getChildArray(txBody, "p").forEach((p, paragraphIndex) => {
5579
+ const orderedChildren = orderedParagraphs?.[paragraphIndex];
5580
+ if (orderedChildren !== void 0 && hasMultipleBulletPPr(p, orderedChildren)) {
5581
+ const split = splitInterleavedParagraph(
5582
+ p,
5583
+ orderedChildren,
5584
+ partPath,
5585
+ nextId,
5586
+ ownerNodeId,
5587
+ ownerOrderingSlot,
5588
+ logicalParagraphIndex
5589
+ );
5590
+ paragraphs.push(...split);
5591
+ logicalParagraphIndex += split.length;
5592
+ return;
5593
+ }
5594
+ paragraphs.push(
5595
+ parseParagraph(
5596
+ p,
5597
+ partPath,
5598
+ nextId,
5599
+ ownerNodeId,
5600
+ ownerOrderingSlot,
5601
+ logicalParagraphIndex,
5602
+ orderedChildren
5603
+ )
5604
+ );
5605
+ logicalParagraphIndex++;
5606
+ });
5607
+ const rawSidecars = collectUnknownSidecars(txBody, KNOWN_TXBODY_CHILDREN, nextId);
5608
+ return {
5609
+ paragraphs,
5610
+ ...properties !== void 0 ? { properties } : {},
5611
+ ...listStyle !== void 0 ? { listStyle } : {},
5612
+ handle: { partPath },
5613
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
5614
+ };
5615
+ }
5616
+ function parseTextStyle(node) {
5617
+ if (node === void 0) return void 0;
5618
+ const defaultParagraph = parseParagraphProperties(getChild(node, "defPPr"));
5619
+ const levels = Array.from(
5620
+ { length: 9 },
5621
+ (_, index) => parseParagraphProperties(getChild(node, `lvl${index + 1}pPr`))
5622
+ );
5623
+ if (defaultParagraph === void 0 && levels.every((level) => level === void 0)) {
5624
+ return void 0;
5625
+ }
5626
+ return { ...defaultParagraph !== void 0 ? { defaultParagraph } : {}, levels };
5627
+ }
5628
+ function hasMultipleBulletPPr(p, orderedChildren) {
5629
+ const pPrList = getChildArray(p, "pPr");
5630
+ let bulletPPrCount = 0;
5631
+ let pPrCounter = 0;
5632
+ for (const child of orderedChildren) {
5633
+ if (orderedLocalName(child) !== "pPr") continue;
5634
+ const pPr = pPrList[pPrCounter];
5635
+ if (pPr !== void 0 && (getChild(pPr, "buChar") !== void 0 || getChild(pPr, "buAutoNum") !== void 0)) {
5636
+ bulletPPrCount++;
5637
+ if (bulletPPrCount >= 2) return true;
5638
+ }
5639
+ pPrCounter++;
5640
+ }
5641
+ return false;
5642
+ }
5643
+ function splitInterleavedParagraph(p, orderedChildren, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex) {
5169
5644
  const pPrList = getChildArray(p, "pPr");
5170
5645
  const rList = getChildArray(p, "r");
5171
5646
  const fldList = getChildArray(p, "fld");
@@ -6298,6 +6773,7 @@ var xmlBuilder = new XMLBuilder({
6298
6773
  suppressEmptyNode: true
6299
6774
  });
6300
6775
  function buildTextBoxXml(params) {
6776
+ const paragraphs = params.paragraphs ?? [{ runs: [{ text: params.text ?? "" }] }];
6301
6777
  return xmlBuilder.build({
6302
6778
  "p:sp": {
6303
6779
  "p:nvSpPr": {
@@ -6312,6 +6788,7 @@ function buildTextBoxXml(params) {
6312
6788
  },
6313
6789
  "p:spPr": {
6314
6790
  "a:xfrm": {
6791
+ ...params.rotation !== void 0 ? { "@_rot": String(params.rotation) } : {},
6315
6792
  "a:off": {
6316
6793
  "@_x": String(params.offsetX),
6317
6794
  "@_y": String(params.offsetY)
@@ -6331,20 +6808,142 @@ function buildTextBoxXml(params) {
6331
6808
  }
6332
6809
  },
6333
6810
  "p:txBody": {
6334
- "a:bodyPr": {
6335
- "@_wrap": "square"
6336
- },
6811
+ "a:bodyPr": createTextBodyPropertiesXml(params.body),
6337
6812
  "a:lstStyle": {},
6338
- "a:p": {
6339
- "a:r": {
6340
- "a:t": textElementValue(params.text)
6341
- },
6342
- "a:endParaRPr": {}
6343
- }
6813
+ "a:p": paragraphs.map(createParagraphXml)
6344
6814
  }
6345
6815
  }
6346
6816
  });
6347
6817
  }
6818
+ function createTextBodyPropertiesXml(body) {
6819
+ return {
6820
+ "@_wrap": "square",
6821
+ ...body?.anchor !== void 0 ? { "@_anchor": verticalAnchorToken(body.anchor) } : {},
6822
+ ...body?.marginLeft !== void 0 ? { "@_lIns": String(body.marginLeft) } : {},
6823
+ ...body?.marginRight !== void 0 ? { "@_rIns": String(body.marginRight) } : {},
6824
+ ...body?.marginTop !== void 0 ? { "@_tIns": String(body.marginTop) } : {},
6825
+ ...body?.marginBottom !== void 0 ? { "@_bIns": String(body.marginBottom) } : {}
6826
+ };
6827
+ }
6828
+ function createParagraphXml(paragraph) {
6829
+ return {
6830
+ ...paragraph.properties !== void 0 ? { "a:pPr": createParagraphPropertiesXml(paragraph.properties) } : {},
6831
+ "a:r": paragraph.runs.map(createTextRunXml),
6832
+ "a:endParaRPr": {}
6833
+ };
6834
+ }
6835
+ function createParagraphPropertiesXml(properties) {
6836
+ return {
6837
+ ...properties.align !== void 0 ? { "@_algn": textAlignToken(properties.align) } : {},
6838
+ ...properties.lineSpacing !== void 0 ? { "a:lnSpc": { "a:spcPts": { "@_val": String(properties.lineSpacing) } } } : {}
6839
+ };
6840
+ }
6841
+ function createTextRunXml(run) {
6842
+ return {
6843
+ ...run.properties !== void 0 ? { "a:rPr": createTextRunPropertiesXml(run.properties) } : {},
6844
+ "a:t": textElementValue(run.text)
6845
+ };
6846
+ }
6847
+ function createTextRunPropertiesXml(properties) {
6848
+ return {
6849
+ ...properties.bold !== void 0 ? { "@_b": boolToken(properties.bold) } : {},
6850
+ ...properties.italic !== void 0 ? { "@_i": boolToken(properties.italic) } : {},
6851
+ ...properties.underline !== void 0 ? { "@_u": underlineStyleToken(properties.underline) } : {},
6852
+ ...properties.strike !== void 0 ? { "@_strike": properties.strike ? "sngStrike" : "noStrike" } : {},
6853
+ ...properties.baseline !== void 0 ? { "@_baseline": String(baselineToken(properties.baseline)) } : {},
6854
+ ...properties.fontSize !== void 0 ? { "@_sz": String(Math.round(properties.fontSize * 100)) } : {},
6855
+ ...properties.charSpacing !== void 0 ? { "@_spc": textPointToken(properties.charSpacing) } : {},
6856
+ ...properties.outline !== void 0 ? { "a:ln": createTextOutlineXml(properties.outline) } : {},
6857
+ ...properties.color !== void 0 ? { "a:solidFill": createSolidFillXml(properties.color) } : {},
6858
+ ...properties.gradientFill !== void 0 ? { "a:gradFill": createGradientFillXml(properties.gradientFill) } : {},
6859
+ ...properties.glow !== void 0 ? { "a:effectLst": { "a:glow": createGlowXml(properties.glow) } } : {},
6860
+ ...properties.highlight !== void 0 ? { "a:highlight": createColorXml(properties.highlight) } : {},
6861
+ ...properties.underline !== void 0 && typeof properties.underline !== "boolean" && properties.underline.color !== void 0 ? { "a:uFill": { "a:solidFill": createSolidFillXml(properties.underline.color) } } : {},
6862
+ ...properties.fontFace !== void 0 ? {
6863
+ "a:latin": { "@_typeface": properties.fontFace },
6864
+ "a:ea": { "@_typeface": properties.fontFace },
6865
+ "a:cs": { "@_typeface": properties.fontFace }
6866
+ } : {}
6867
+ };
6868
+ }
6869
+ function createSolidFillXml(color) {
6870
+ return createColorXml(color);
6871
+ }
6872
+ function createColorXml(color) {
6873
+ if (!/^[0-9A-Fa-f]{6}$/.test(color.hex)) {
6874
+ throw new Error("buildTextBoxXml: color hex must be a 6-digit RGB value");
6875
+ }
6876
+ return {
6877
+ "a:srgbClr": {
6878
+ "@_val": color.hex.toUpperCase()
6879
+ }
6880
+ };
6881
+ }
6882
+ function createGradientFillXml(fill) {
6883
+ return {
6884
+ "a:gsLst": {
6885
+ "a:gs": fill.stops.map((stop) => ({
6886
+ "@_pos": String(stop.position),
6887
+ ...createColorXml(stop.color)
6888
+ }))
6889
+ },
6890
+ "a:lin": {
6891
+ "@_ang": String(fill.angle ?? 0),
6892
+ "@_scaled": "1"
6893
+ }
6894
+ };
6895
+ }
6896
+ function createTextOutlineXml(outline) {
6897
+ return {
6898
+ ...outline.width !== void 0 ? { "@_w": String(outline.width) } : {},
6899
+ ...outline.color !== void 0 ? { "a:solidFill": createSolidFillXml(outline.color) } : {}
6900
+ };
6901
+ }
6902
+ function createGlowXml(glow) {
6903
+ return {
6904
+ "@_rad": String(glow.radius),
6905
+ ...createColorXml(glow.color)
6906
+ };
6907
+ }
6908
+ function underlineStyleToken(underline) {
6909
+ if (typeof underline === "boolean") return underline ? "sng" : "none";
6910
+ return underline.style ?? "sng";
6911
+ }
6912
+ function baselineToken(baseline) {
6913
+ if (baseline === "superscript") return 3e4;
6914
+ return -25e3;
6915
+ }
6916
+ function textPointToken(value) {
6917
+ if (!Number.isInteger(value) || value < -4e5 || value > 4e5) {
6918
+ throw new Error("buildTextBoxXml: charSpacing must be an integer between -400000 and 400000");
6919
+ }
6920
+ return String(value);
6921
+ }
6922
+ function boolToken(value) {
6923
+ return value ? "1" : "0";
6924
+ }
6925
+ function textAlignToken(align) {
6926
+ switch (align) {
6927
+ case "left":
6928
+ return "l";
6929
+ case "center":
6930
+ return "ctr";
6931
+ case "right":
6932
+ return "r";
6933
+ case "justify":
6934
+ return "just";
6935
+ }
6936
+ }
6937
+ function verticalAnchorToken(anchor) {
6938
+ switch (anchor) {
6939
+ case "top":
6940
+ return "t";
6941
+ case "middle":
6942
+ return "ctr";
6943
+ case "bottom":
6944
+ return "b";
6945
+ }
6946
+ }
6348
6947
  function buildConnectorXml(params) {
6349
6948
  return xmlBuilder.build({
6350
6949
  "p:cxnSp": {
@@ -6353,16 +6952,7 @@ function buildConnectorXml(params) {
6353
6952
  "@_id": params.shapeId,
6354
6953
  "@_name": params.name
6355
6954
  },
6356
- "p:cNvCxnSpPr": {
6357
- "a:stCxn": {
6358
- "@_id": params.startShapeId,
6359
- "@_idx": String(params.startConnectionSiteIndex)
6360
- },
6361
- "a:endCxn": {
6362
- "@_id": params.endShapeId,
6363
- "@_idx": String(params.endConnectionSiteIndex)
6364
- }
6365
- },
6955
+ "p:cNvCxnSpPr": createConnectorConnectionXml(params),
6366
6956
  "p:nvPr": {}
6367
6957
  },
6368
6958
  "p:spPr": {
@@ -6385,6 +6975,22 @@ function buildConnectorXml(params) {
6385
6975
  }
6386
6976
  });
6387
6977
  }
6978
+ function createConnectorConnectionXml(params) {
6979
+ return {
6980
+ ...params.startShapeId !== void 0 && params.startConnectionSiteIndex !== void 0 ? {
6981
+ "a:stCxn": {
6982
+ "@_id": params.startShapeId,
6983
+ "@_idx": String(params.startConnectionSiteIndex)
6984
+ }
6985
+ } : {},
6986
+ ...params.endShapeId !== void 0 && params.endConnectionSiteIndex !== void 0 ? {
6987
+ "a:endCxn": {
6988
+ "@_id": params.endShapeId,
6989
+ "@_idx": String(params.endConnectionSiteIndex)
6990
+ }
6991
+ } : {}
6992
+ };
6993
+ }
6388
6994
  function createConnectorLineXml(params) {
6389
6995
  return {
6390
6996
  "a:solidFill": {
@@ -6424,8 +7030,27 @@ var CONNECTOR_PRESETS = /* @__PURE__ */ new Set([
6424
7030
  "bentConnector3",
6425
7031
  "curvedConnector3"
6426
7032
  ]);
6427
- var ARROW_TYPES = /* @__PURE__ */ new Set(["triangle", "stealth", "diamond", "oval", "arrow"]);
6428
- var ARROW_SIZES = /* @__PURE__ */ new Set(["sm", "med", "lg"]);
7033
+ var ARROW_TYPES2 = /* @__PURE__ */ new Set(["triangle", "stealth", "diamond", "oval", "arrow"]);
7034
+ var ARROW_SIZES2 = /* @__PURE__ */ new Set(["sm", "med", "lg"]);
7035
+ var UNDERLINE_STYLES = /* @__PURE__ */ new Set([
7036
+ "sng",
7037
+ "dbl",
7038
+ "heavy",
7039
+ "dotted",
7040
+ "dottedHeavy",
7041
+ "dash",
7042
+ "dashHeavy",
7043
+ "dashLong",
7044
+ "dashLongHeavy",
7045
+ "dotDash",
7046
+ "dotDashHeavy",
7047
+ "dotDotDash",
7048
+ "dotDotDashHeavy",
7049
+ "wavy",
7050
+ "wavyHeavy",
7051
+ "wavyDbl",
7052
+ "none"
7053
+ ]);
6429
7054
  function findShapeNodeBySourceHandle(source, handle) {
6430
7055
  for (const slide of source.slides) {
6431
7056
  const shape = findShapeNodeInTree(slide.shapes, handle);
@@ -6489,6 +7114,92 @@ function updateShapeTransform(source, handle, transform) {
6489
7114
  ]
6490
7115
  };
6491
7116
  }
7117
+ function setShapeFill(source, handle, fill) {
7118
+ assertEditableShapeFill(fill, "setShapeFill");
7119
+ if (handle.nodeId === void 0) {
7120
+ throw new Error("setShapeFill: shape fill edit requires a node id");
7121
+ }
7122
+ let matched = false;
7123
+ let changed = false;
7124
+ const slides = source.slides.map((slide) => {
7125
+ let slideChanged = false;
7126
+ const shapes = slide.shapes.map((shape) => {
7127
+ if (!sourceHandlesEqual(shape.handle, handle)) return shape;
7128
+ matched = true;
7129
+ if (shape.kind !== "shape") {
7130
+ throw new Error("setShapeFill: only top-level sp shapes support fill edits");
7131
+ }
7132
+ if (hasAlternateContentSidecar(shape)) {
7133
+ throw new Error("setShapeFill: shapes inside AlternateContent are not supported");
7134
+ }
7135
+ const nextFill = toSourceFill(fill);
7136
+ if (sourceFillEqual(shape.fill, nextFill)) return shape;
7137
+ changed = true;
7138
+ slideChanged = true;
7139
+ return {
7140
+ ...shape,
7141
+ fill: nextFill
7142
+ };
7143
+ });
7144
+ return slideChanged ? { ...slide, shapes } : slide;
7145
+ });
7146
+ if (!matched) {
7147
+ if (source.slides.some((slide) => hasNestedShapeNodeWithHandle(slide.shapes, handle))) {
7148
+ throw new Error("setShapeFill: nested group shape editing is not supported");
7149
+ }
7150
+ throw new Error("setShapeFill: shape handle was not found in PptxSourceModel source");
7151
+ }
7152
+ if (!changed) return source;
7153
+ return {
7154
+ ...source,
7155
+ slides,
7156
+ edits: appendShapeFillEdit(source.edits ?? [], handle, fill)
7157
+ };
7158
+ }
7159
+ function setShapeOutline(source, handle, outline) {
7160
+ assertEditableShapeOutline(outline, "setShapeOutline");
7161
+ if (handle.nodeId === void 0) {
7162
+ throw new Error("setShapeOutline: shape outline edit requires a node id");
7163
+ }
7164
+ let matched = false;
7165
+ let changed = false;
7166
+ const slides = source.slides.map((slide) => {
7167
+ let slideChanged = false;
7168
+ const shapes = slide.shapes.map((shape) => {
7169
+ if (!sourceHandlesEqual(shape.handle, handle)) return shape;
7170
+ matched = true;
7171
+ if (shape.kind !== "shape" && shape.kind !== "connector") {
7172
+ throw new Error(
7173
+ "setShapeOutline: only top-level sp and cxnSp shapes support outline edits"
7174
+ );
7175
+ }
7176
+ if (hasAlternateContentSidecar(shape)) {
7177
+ throw new Error("setShapeOutline: shapes inside AlternateContent are not supported");
7178
+ }
7179
+ const nextOutline = patchSourceOutline(shape.outline, outline);
7180
+ if (sourceOutlineEqual(shape.outline, nextOutline)) return shape;
7181
+ changed = true;
7182
+ slideChanged = true;
7183
+ return {
7184
+ ...shape,
7185
+ outline: nextOutline
7186
+ };
7187
+ });
7188
+ return slideChanged ? { ...slide, shapes } : slide;
7189
+ });
7190
+ if (!matched) {
7191
+ if (source.slides.some((slide) => hasNestedShapeNodeWithHandle(slide.shapes, handle))) {
7192
+ throw new Error("setShapeOutline: nested group shape editing is not supported");
7193
+ }
7194
+ throw new Error("setShapeOutline: shape handle was not found in PptxSourceModel source");
7195
+ }
7196
+ if (!changed) return source;
7197
+ return {
7198
+ ...source,
7199
+ slides,
7200
+ edits: appendShapeOutlineEdit(source.edits ?? [], handle, outline)
7201
+ };
7202
+ }
6492
7203
  function addTextBox(source, slideHandle, input) {
6493
7204
  assertTextBoxInput(input);
6494
7205
  const slideIndex = source.slides.findIndex(
@@ -6509,7 +7220,9 @@ function addTextBox(source, slideHandle, input) {
6509
7220
  offsetY: input.offsetY,
6510
7221
  width: input.width,
6511
7222
  height: input.height,
6512
- text: input.text
7223
+ ...input.rotation !== void 0 ? { rotation: input.rotation } : {},
7224
+ ...input.paragraphs !== void 0 ? { paragraphs: input.paragraphs } : { text: input.text },
7225
+ ...input.body !== void 0 ? { body: input.body } : {}
6513
7226
  });
6514
7227
  const shape = parseShapeNodeXml(xml, slide.partPath, orderingSlot);
6515
7228
  const slides = source.slides.map(
@@ -6541,14 +7254,14 @@ function addConnector(source, slideHandle, input) {
6541
7254
  throw new Error("addConnector: slide handle was not found in PptxSourceModel source");
6542
7255
  }
6543
7256
  const slide = source.slides[slideIndex];
6544
- const startShape = requireConnectorTargetShape(slide, input.start.shapeHandle, "start");
6545
- const endShape = requireConnectorTargetShape(slide, input.end.shapeHandle, "end");
7257
+ const startShape = input.start !== void 0 ? requireConnectorTargetShape(slide, input.start.shapeHandle, "start") : void 0;
7258
+ const endShape = input.end !== void 0 ? requireConnectorTargetShape(slide, input.end.shapeHandle, "end") : void 0;
6546
7259
  const shapeId = nextShapeId(slide.shapes, source.edits ?? [], slide.partPath);
6547
7260
  const shapeIdValue = String(shapeId);
6548
7261
  const name = input.name?.trim() || `Connector ${shapeIdValue}`;
6549
7262
  const orderingSlot = nextOrderingSlot(slide.shapes);
6550
- const startShapeId = String(startShape.nodeId);
6551
- const endShapeId = String(endShape.nodeId);
7263
+ const startShapeId = startShape !== void 0 ? String(startShape.nodeId) : void 0;
7264
+ const endShapeId = endShape !== void 0 ? String(endShape.nodeId) : void 0;
6552
7265
  const xml = buildConnectorXml({
6553
7266
  shapeId: shapeIdValue,
6554
7267
  name,
@@ -6557,10 +7270,14 @@ function addConnector(source, slideHandle, input) {
6557
7270
  offsetY: input.offsetY,
6558
7271
  width: input.width,
6559
7272
  height: input.height,
6560
- startShapeId,
6561
- startConnectionSiteIndex: input.start.connectionSiteIndex,
6562
- endShapeId,
6563
- endConnectionSiteIndex: input.end.connectionSiteIndex,
7273
+ ...startShapeId !== void 0 && input.start !== void 0 ? {
7274
+ startShapeId,
7275
+ startConnectionSiteIndex: input.start.connectionSiteIndex
7276
+ } : {},
7277
+ ...endShapeId !== void 0 && input.end !== void 0 ? {
7278
+ endShapeId,
7279
+ endConnectionSiteIndex: input.end.connectionSiteIndex
7280
+ } : {},
6564
7281
  ...input.outline !== void 0 ? { outline: input.outline } : {}
6565
7282
  });
6566
7283
  const connector = parseShapeNodeXml(xml, slide.partPath, orderingSlot);
@@ -6579,8 +7296,8 @@ function addConnector(source, slideHandle, input) {
6579
7296
  kind: "addConnector",
6580
7297
  slidePartPath: slide.partPath,
6581
7298
  shapeId: shapeIdValue,
6582
- startShapeId,
6583
- endShapeId,
7299
+ ...startShapeId !== void 0 ? { startShapeId } : {},
7300
+ ...endShapeId !== void 0 ? { endShapeId } : {},
6584
7301
  xml
6585
7302
  }
6586
7303
  ]
@@ -6597,8 +7314,8 @@ function deleteShape(source, handle) {
6597
7314
  const nextShapes = slide.shapes.filter((shape) => {
6598
7315
  if (!sourceHandlesEqual(shape.handle, handle)) return true;
6599
7316
  found = shape;
6600
- if (shape.kind !== "shape") {
6601
- throw new Error("deleteShape: only top-level sp shapes can be deleted");
7317
+ if (shape.kind !== "shape" && shape.kind !== "connector") {
7318
+ throw new Error("deleteShape: only top-level sp or cxnSp shapes can be deleted");
6602
7319
  }
6603
7320
  if (hasAlternateContentSidecar(shape)) {
6604
7321
  throw new Error("deleteShape: shapes inside AlternateContent are not supported");
@@ -6638,8 +7355,101 @@ function deleteShape(source, handle) {
6638
7355
  ]
6639
7356
  };
6640
7357
  }
6641
- function shapeTransformPositionAndSizeEqual(current, next) {
6642
- return current?.offsetX === next.offsetX && current.offsetY === next.offsetY && current.width === next.width && current.height === next.height;
7358
+ function shapeTransformPositionAndSizeEqual(current, next) {
7359
+ return current?.offsetX === next.offsetX && current.offsetY === next.offsetY && current.width === next.width && current.height === next.height;
7360
+ }
7361
+ function patchSourceOutline(current, patch) {
7362
+ return {
7363
+ ...current ?? {},
7364
+ ...patch.width !== void 0 ? { width: patch.width } : {},
7365
+ ...patch.fill !== void 0 ? { fill: toSourceFill(patch.fill) } : {}
7366
+ };
7367
+ }
7368
+ function appendShapeFillEdit(edits, handle, fill) {
7369
+ const retainedEdits = edits.filter(
7370
+ (edit) => edit.kind !== "updateShapeFill" || !sourceHandlesEqual(edit.handle, handle)
7371
+ );
7372
+ return [...retainedEdits, { kind: "updateShapeFill", handle, fill }];
7373
+ }
7374
+ function appendShapeOutlineEdit(edits, handle, outline) {
7375
+ let outlineEdit = {
7376
+ kind: "updateShapeOutline",
7377
+ handle,
7378
+ outline
7379
+ };
7380
+ const retainedEdits = [];
7381
+ for (const edit of edits) {
7382
+ if (edit.kind !== "updateShapeOutline" || !sourceHandlesEqual(edit.handle, handle)) {
7383
+ retainedEdits.push(edit);
7384
+ continue;
7385
+ }
7386
+ outlineEdit = {
7387
+ ...outlineEdit,
7388
+ outline: mergeEditableShapeOutline(edit.outline, outlineEdit.outline)
7389
+ };
7390
+ }
7391
+ return [...retainedEdits, outlineEdit];
7392
+ }
7393
+ function mergeEditableShapeOutline(base, patch) {
7394
+ return {
7395
+ ...base.width !== void 0 ? { width: base.width } : {},
7396
+ ...base.fill !== void 0 ? { fill: base.fill } : {},
7397
+ ...patch.width !== void 0 ? { width: patch.width } : {},
7398
+ ...patch.fill !== void 0 ? { fill: patch.fill } : {}
7399
+ };
7400
+ }
7401
+ function toSourceFill(fill) {
7402
+ if (fill.kind === "none") return { kind: "none" };
7403
+ return {
7404
+ kind: "solid",
7405
+ color: { kind: "srgb", hex: fill.color.hex }
7406
+ };
7407
+ }
7408
+ function assertEditableShapeFill(fill, operationName) {
7409
+ if (fill.kind === "none") return;
7410
+ if (fill.kind !== "solid") {
7411
+ throw new Error(`${operationName}: only solid and none fills are supported`);
7412
+ }
7413
+ if (fill.color.kind !== "srgb") {
7414
+ throw new Error(`${operationName}: only srgb solid fill colors are supported`);
7415
+ }
7416
+ if (!/^[0-9A-Fa-f]{6}$/.test(fill.color.hex)) {
7417
+ throw new Error(`${operationName}: srgb fill color must be a 6-digit hex value`);
7418
+ }
7419
+ }
7420
+ function assertEditableShapeOutline(outline, operationName) {
7421
+ if (outline.width === void 0 && outline.fill === void 0) {
7422
+ throw new Error(`${operationName}: outline must set width or fill`);
7423
+ }
7424
+ if (outline.width !== void 0) {
7425
+ assertPositiveFiniteEmu(outline.width, operationName, "width");
7426
+ }
7427
+ if (outline.fill !== void 0) assertEditableShapeFill(outline.fill, operationName);
7428
+ }
7429
+ function sourceFillEqual(left, right) {
7430
+ return stableValueEqual(left ?? {}, right ?? {});
7431
+ }
7432
+ function sourceOutlineEqual(left, right) {
7433
+ return stableValueEqual(left ?? {}, right ?? {});
7434
+ }
7435
+ function stableValueEqual(left, right) {
7436
+ if (Object.is(left, right)) return true;
7437
+ if (Array.isArray(left) || Array.isArray(right)) {
7438
+ if (!Array.isArray(left) || !Array.isArray(right)) return false;
7439
+ if (left.length !== right.length) return false;
7440
+ return left.every((value, index) => stableValueEqual(value, right[index]));
7441
+ }
7442
+ if (isPlainRecord(left) || isPlainRecord(right)) {
7443
+ if (!isPlainRecord(left) || !isPlainRecord(right)) return false;
7444
+ const leftKeys = Object.keys(left).sort();
7445
+ const rightKeys = Object.keys(right).sort();
7446
+ if (!stableValueEqual(leftKeys, rightKeys)) return false;
7447
+ return leftKeys.every((key) => stableValueEqual(left[key], right[key]));
7448
+ }
7449
+ return false;
7450
+ }
7451
+ function isPlainRecord(value) {
7452
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6643
7453
  }
6644
7454
  function hasEditableTransform(shape) {
6645
7455
  return shape.kind !== "raw" && shape.transform !== void 0;
@@ -6649,13 +7459,208 @@ function assertTextBoxInput(input) {
6649
7459
  assertFiniteEmu(input.offsetY, "addTextBox", "offsetY");
6650
7460
  assertPositiveFiniteEmu(input.width, "addTextBox", "width");
6651
7461
  assertPositiveFiniteEmu(input.height, "addTextBox", "height");
6652
- if (typeof input.text !== "string") {
6653
- throw new Error("addTextBox: text must be a string");
7462
+ if (input.rotation !== void 0) {
7463
+ assertFiniteIntegerNumber(input.rotation, "addTextBox", "rotation");
7464
+ }
7465
+ if (input.text !== void 0 && input.paragraphs !== void 0) {
7466
+ throw new Error("addTextBox: specify either text or paragraphs, not both");
7467
+ }
7468
+ if (input.text === void 0 && input.paragraphs === void 0) {
7469
+ throw new Error("addTextBox: text or paragraphs must be provided");
7470
+ }
7471
+ if (input.text !== void 0 && typeof input.text !== "string") {
7472
+ throw new Error("addTextBox: text must be a string when provided");
7473
+ }
7474
+ if (input.paragraphs !== void 0) {
7475
+ assertTextBoxParagraphs(input.paragraphs);
7476
+ }
7477
+ if (input.body !== void 0) {
7478
+ assertTextBoxBody(input.body, "body");
6654
7479
  }
6655
7480
  if (input.name !== void 0 && input.name.trim() === "") {
6656
7481
  throw new Error("addTextBox: name must be a non-empty string when provided");
6657
7482
  }
6658
7483
  }
7484
+ function assertTextBoxParagraphs(paragraphs) {
7485
+ if (!isArrayValue(paragraphs) || paragraphs.length === 0) {
7486
+ throw new Error("addTextBox: paragraphs must contain at least one paragraph");
7487
+ }
7488
+ paragraphs.forEach((paragraph, paragraphIndex) => {
7489
+ if (!isPlainRecord(paragraph)) {
7490
+ throw new Error(`addTextBox: paragraphs[${paragraphIndex}] must be an object`);
7491
+ }
7492
+ const runs = paragraph.runs;
7493
+ if (!isArrayValue(runs) || runs.length === 0) {
7494
+ throw new Error(
7495
+ `addTextBox: paragraphs[${paragraphIndex}].runs must contain at least one run`
7496
+ );
7497
+ }
7498
+ assertTextBoxParagraphProperties(paragraph.properties, paragraphIndex);
7499
+ runs.forEach((run, runIndex) => assertTextBoxRun(run, paragraphIndex, runIndex));
7500
+ });
7501
+ }
7502
+ function assertTextBoxParagraphProperties(properties, paragraphIndex) {
7503
+ if (properties === void 0) return;
7504
+ if (!isPlainRecord(properties)) {
7505
+ throw new Error(`addTextBox: paragraphs[${paragraphIndex}].properties must be an object`);
7506
+ }
7507
+ const align = properties.align;
7508
+ const lineSpacing = properties.lineSpacing;
7509
+ if (align !== void 0 && align !== "left" && align !== "center" && align !== "right" && align !== "justify") {
7510
+ throw new Error(`addTextBox: paragraphs[${paragraphIndex}].properties.align is not supported`);
7511
+ }
7512
+ if (lineSpacing !== void 0) {
7513
+ assertPositiveFiniteIntegerNumber(
7514
+ lineSpacing,
7515
+ "addTextBox",
7516
+ `paragraphs[${paragraphIndex}].properties.lineSpacing`
7517
+ );
7518
+ }
7519
+ }
7520
+ function assertTextBoxRun(run, paragraphIndex, runIndex) {
7521
+ const path = `paragraphs[${paragraphIndex}].runs[${runIndex}]`;
7522
+ if (!isPlainRecord(run)) {
7523
+ throw new Error(`addTextBox: ${path} must be an object`);
7524
+ }
7525
+ if (typeof run.text !== "string") {
7526
+ throw new Error(`addTextBox: ${path}.text must be a string`);
7527
+ }
7528
+ assertTextBoxRunProperties(run.properties, path);
7529
+ }
7530
+ function assertTextBoxRunProperties(properties, path) {
7531
+ if (properties === void 0) return;
7532
+ if (!isPlainRecord(properties)) {
7533
+ throw new Error(`addTextBox: ${path}.properties must be an object`);
7534
+ }
7535
+ const fontFace = properties.fontFace;
7536
+ const fontSize = properties.fontSize;
7537
+ const color = properties.color;
7538
+ const gradientFill = properties.gradientFill;
7539
+ const underline = properties.underline;
7540
+ const baseline = properties.baseline;
7541
+ const highlight = properties.highlight;
7542
+ const glow = properties.glow;
7543
+ const outline = properties.outline;
7544
+ const charSpacing = properties.charSpacing;
7545
+ if (fontFace !== void 0 && (typeof fontFace !== "string" || fontFace.trim() === "")) {
7546
+ throw new Error(`addTextBox: ${path}.properties.fontFace must be a non-empty string`);
7547
+ }
7548
+ if (fontSize !== void 0) {
7549
+ assertPositiveFiniteNumber(fontSize, "addTextBox", `${path}.properties.fontSize`);
7550
+ }
7551
+ assertBooleanOrUndefined(properties.bold, "addTextBox", `${path}.properties.bold`);
7552
+ assertBooleanOrUndefined(properties.italic, "addTextBox", `${path}.properties.italic`);
7553
+ assertBooleanOrUndefined(properties.strike, "addTextBox", `${path}.properties.strike`);
7554
+ if (color !== void 0) assertTextBoxColor(color, `${path}.properties.color`);
7555
+ if (gradientFill !== void 0) {
7556
+ if (color !== void 0) {
7557
+ throw new Error(`addTextBox: ${path}.properties cannot set both color and gradientFill`);
7558
+ }
7559
+ assertTextBoxGradientFill(gradientFill, `${path}.properties.gradientFill`);
7560
+ }
7561
+ if (underline !== void 0) {
7562
+ assertTextBoxUnderline(underline, `${path}.properties.underline`);
7563
+ }
7564
+ if (baseline !== void 0) {
7565
+ assertTextBoxBaseline(baseline, `${path}.properties.baseline`);
7566
+ }
7567
+ if (highlight !== void 0) {
7568
+ assertTextBoxColor(highlight, `${path}.properties.highlight`);
7569
+ }
7570
+ if (glow !== void 0) assertTextBoxGlow(glow, `${path}.properties.glow`);
7571
+ if (outline !== void 0) {
7572
+ assertTextBoxOutline(outline, `${path}.properties.outline`);
7573
+ }
7574
+ if (charSpacing !== void 0) {
7575
+ assertTextPointNumber(charSpacing, "addTextBox", `${path}.properties.charSpacing`);
7576
+ }
7577
+ }
7578
+ function assertTextBoxColor(color, path) {
7579
+ if (!isPlainRecord(color)) {
7580
+ throw new Error(`addTextBox: ${path} must be an srgb 6-digit hex color`);
7581
+ }
7582
+ if (color.kind !== "srgb" || typeof color.hex !== "string" || !/^[0-9A-Fa-f]{6}$/.test(color.hex)) {
7583
+ throw new Error(`addTextBox: ${path} must be an srgb 6-digit hex color`);
7584
+ }
7585
+ }
7586
+ function assertTextBoxGradientFill(fill, path) {
7587
+ if (!isPlainRecord(fill)) {
7588
+ throw new Error(`addTextBox: ${path} must be a gradient fill object`);
7589
+ }
7590
+ const stops = fill.stops;
7591
+ if (!isArrayValue(stops) || stops.length < 2) {
7592
+ throw new Error(`addTextBox: ${path}.stops must contain at least two stops`);
7593
+ }
7594
+ if (fill.angle !== void 0)
7595
+ assertFiniteIntegerNumber(fill.angle, "addTextBox", `${path}.angle`);
7596
+ stops.forEach((stop, index) => {
7597
+ if (!isPlainRecord(stop)) {
7598
+ throw new Error(`addTextBox: ${path}.stops[${index}] must be an object`);
7599
+ }
7600
+ const position = stop.position;
7601
+ assertFiniteIntegerNumber(position, "addTextBox", `${path}.stops[${index}].position`);
7602
+ if (typeof position !== "number" || position < 0 || position > 1e5) {
7603
+ throw new Error(`addTextBox: ${path}.stops[${index}].position must be between 0 and 100000`);
7604
+ }
7605
+ assertTextBoxColor(stop.color, `${path}.stops[${index}].color`);
7606
+ });
7607
+ }
7608
+ function isArrayValue(value) {
7609
+ return Array.isArray(value);
7610
+ }
7611
+ function assertTextBoxUnderline(underline, path) {
7612
+ if (typeof underline === "boolean") return;
7613
+ if (!isPlainRecord(underline)) {
7614
+ throw new Error(`addTextBox: ${path} must be a boolean or underline options object`);
7615
+ }
7616
+ const style = underline.style ?? "sng";
7617
+ if (typeof style !== "string" || !UNDERLINE_STYLES.has(style)) {
7618
+ throw new Error(`addTextBox: ${path}.style is not supported`);
7619
+ }
7620
+ if (underline.color !== void 0) {
7621
+ assertTextBoxColor(underline.color, `${path}.color`);
7622
+ }
7623
+ }
7624
+ function assertTextBoxBaseline(baseline, path) {
7625
+ if (baseline === "subscript" || baseline === "superscript") return;
7626
+ throw new Error(`addTextBox: ${path} must be subscript or superscript`);
7627
+ }
7628
+ function assertTextBoxGlow(glow, path) {
7629
+ if (!isPlainRecord(glow)) {
7630
+ throw new Error(`addTextBox: ${path} must be an object`);
7631
+ }
7632
+ assertPositiveFiniteEmu(glow.radius, "addTextBox", `${path}.radius`);
7633
+ assertTextBoxColor(glow.color, `${path}.color`);
7634
+ }
7635
+ function assertTextBoxOutline(outline, path) {
7636
+ if (!isPlainRecord(outline)) {
7637
+ throw new Error(`addTextBox: ${path} must be an object`);
7638
+ }
7639
+ if (outline.width === void 0 && outline.color === void 0) {
7640
+ throw new Error(`addTextBox: ${path} must set width or color`);
7641
+ }
7642
+ if (outline.width !== void 0) {
7643
+ assertPositiveFiniteEmu(outline.width, "addTextBox", `${path}.width`);
7644
+ }
7645
+ if (outline.color !== void 0) assertTextBoxColor(outline.color, `${path}.color`);
7646
+ }
7647
+ function assertTextBoxBody(body, path) {
7648
+ if (!isPlainRecord(body)) {
7649
+ throw new Error(`addTextBox: ${path} must be an object`);
7650
+ }
7651
+ if (body.anchor !== void 0 && body.anchor !== "top" && body.anchor !== "middle" && body.anchor !== "bottom") {
7652
+ throw new Error("addTextBox: body.anchor is not supported");
7653
+ }
7654
+ if (body.marginLeft !== void 0)
7655
+ assertFiniteEmu(body.marginLeft, "addTextBox", "body.marginLeft");
7656
+ if (body.marginRight !== void 0) {
7657
+ assertFiniteEmu(body.marginRight, "addTextBox", "body.marginRight");
7658
+ }
7659
+ if (body.marginTop !== void 0) assertFiniteEmu(body.marginTop, "addTextBox", "body.marginTop");
7660
+ if (body.marginBottom !== void 0) {
7661
+ assertFiniteEmu(body.marginBottom, "addTextBox", "body.marginBottom");
7662
+ }
7663
+ }
6659
7664
  function assertConnectorInput(input) {
6660
7665
  assertFiniteEmu(input.offsetX, "addConnector", "offsetX");
6661
7666
  assertFiniteEmu(input.offsetY, "addConnector", "offsetY");
@@ -6666,8 +7671,9 @@ function assertConnectorInput(input) {
6666
7671
  "addConnector: preset must be straightConnector1, bentConnector3, or curvedConnector3"
6667
7672
  );
6668
7673
  }
6669
- assertConnectionSiteIndex(input.start.connectionSiteIndex, "start");
6670
- assertConnectionSiteIndex(input.end.connectionSiteIndex, "end");
7674
+ if (input.start !== void 0)
7675
+ assertConnectionSiteIndex(input.start.connectionSiteIndex, "start");
7676
+ if (input.end !== void 0) assertConnectionSiteIndex(input.end.connectionSiteIndex, "end");
6671
7677
  if (input.name !== void 0 && input.name.trim() === "") {
6672
7678
  throw new Error("addConnector: name must be a non-empty string when provided");
6673
7679
  }
@@ -6683,23 +7689,49 @@ function assertConnectionSiteIndex(value, fieldName) {
6683
7689
  }
6684
7690
  function assertArrowEndpoint(endpoint, fieldName) {
6685
7691
  if (endpoint === void 0) return;
6686
- if (!ARROW_TYPES.has(endpoint.type)) {
7692
+ if (!ARROW_TYPES2.has(endpoint.type)) {
6687
7693
  throw new Error(`addConnector: outline.${fieldName}.type is not supported`);
6688
7694
  }
6689
- if (!ARROW_SIZES.has(endpoint.width)) {
7695
+ if (!ARROW_SIZES2.has(endpoint.width)) {
6690
7696
  throw new Error(`addConnector: outline.${fieldName}.width is not supported`);
6691
7697
  }
6692
- if (!ARROW_SIZES.has(endpoint.length)) {
7698
+ if (!ARROW_SIZES2.has(endpoint.length)) {
6693
7699
  throw new Error(`addConnector: outline.${fieldName}.length is not supported`);
6694
7700
  }
6695
7701
  }
7702
+ function assertBooleanOrUndefined(value, operationName, fieldName) {
7703
+ if (value !== void 0 && typeof value !== "boolean") {
7704
+ throw new Error(`${operationName}: ${fieldName} must be a boolean value`);
7705
+ }
7706
+ }
7707
+ function assertFiniteIntegerNumber(value, operationName, fieldName) {
7708
+ if (!Number.isInteger(value)) {
7709
+ throw new Error(`${operationName}: ${fieldName} must be a finite integer`);
7710
+ }
7711
+ }
7712
+ function assertPositiveFiniteNumber(value, operationName, fieldName) {
7713
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
7714
+ throw new Error(`${operationName}: ${fieldName} must be a finite positive number`);
7715
+ }
7716
+ }
7717
+ function assertPositiveFiniteIntegerNumber(value, operationName, fieldName) {
7718
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
7719
+ throw new Error(`${operationName}: ${fieldName} must be a finite positive integer`);
7720
+ }
7721
+ }
7722
+ function assertTextPointNumber(value, operationName, fieldName) {
7723
+ assertFiniteIntegerNumber(value, operationName, fieldName);
7724
+ if (typeof value !== "number" || value < -4e5 || value > 4e5) {
7725
+ throw new Error(`${operationName}: ${fieldName} must be between -400000 and 400000`);
7726
+ }
7727
+ }
6696
7728
  function assertFiniteEmu(value, operationName, fieldName) {
6697
- if (!Number.isFinite(value)) {
7729
+ if (typeof value !== "number" || !Number.isFinite(value)) {
6698
7730
  throw new Error(`${operationName}: ${fieldName} must be a finite EMU value`);
6699
7731
  }
6700
7732
  }
6701
7733
  function assertPositiveFiniteEmu(value, operationName, fieldName) {
6702
- if (!Number.isFinite(value) || value <= 0) {
7734
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
6703
7735
  throw new Error(`${operationName}: ${fieldName} must be a finite positive EMU value`);
6704
7736
  }
6705
7737
  }
@@ -7084,6 +8116,45 @@ function duplicateSlide(source, slideHandle) {
7084
8116
  ]
7085
8117
  };
7086
8118
  }
8119
+ function moveSlide(source, slideHandle, input) {
8120
+ assertValidSlideIndex(input.toIndex, source.slides.length, "moveSlide");
8121
+ const slideIndex = source.slides.findIndex(
8122
+ (slide2) => sourceHandlesEqual(slide2.handle, slideHandle)
8123
+ );
8124
+ if (slideIndex === -1) {
8125
+ throw new Error("moveSlide: slide handle was not found in PptxSourceModel source");
8126
+ }
8127
+ if (slideIndex === input.toIndex) return source;
8128
+ const slide = source.slides[slideIndex];
8129
+ const presentationRels = requirePartRelationships(
8130
+ source,
8131
+ source.presentation.partPath,
8132
+ "moveSlide"
8133
+ );
8134
+ const presentationRelationship = requireSlideRelationship(
8135
+ source,
8136
+ presentationRels,
8137
+ slide.partPath,
8138
+ "moveSlide"
8139
+ );
8140
+ return {
8141
+ ...source,
8142
+ presentation: {
8143
+ ...source.presentation,
8144
+ slidePartPaths: moveReadonly(source.presentation.slidePartPaths, slideIndex, input.toIndex)
8145
+ },
8146
+ slides: moveReadonly(source.slides, slideIndex, input.toIndex),
8147
+ edits: [
8148
+ ...source.edits ?? [],
8149
+ {
8150
+ kind: "moveSlide",
8151
+ slidePartPath: slide.partPath,
8152
+ relationshipId: presentationRelationship.id,
8153
+ toIndex: input.toIndex
8154
+ }
8155
+ ]
8156
+ };
8157
+ }
7087
8158
  function deleteSlide(source, slideHandle) {
7088
8159
  if (source.slides.length <= 1) {
7089
8160
  throw new Error("deleteSlide: cannot delete the last slide");
@@ -7166,766 +8237,500 @@ function createNotesSlideCopy(source, sourceSlide, slideRelationships, newSlideP
7166
8237
  (relationships) => relationships.sourcePartPath === notesPartPath
7167
8238
  );
7168
8239
  return {
7169
- slideRelationshipId: notesRelationship.id,
7170
- newPartPath,
7171
- contentType,
7172
- raw,
7173
- ...notesRelationships === void 0 ? {} : {
7174
- relationships: {
7175
- sourcePartPath: newPartPath,
7176
- relationships: notesRelationships.relationships.map(
7177
- (relationship) => relationship.type === SLIDE_REL_TYPE && relationship.targetMode !== "External" ? { ...relationship, target: relativeTarget(newPartPath, newSlidePartPath) } : relationship
7178
- )
7179
- }
7180
- }
7181
- };
7182
- }
7183
- function withPartPath(slide, partPath) {
7184
- return {
7185
- ...slide,
7186
- partPath,
7187
- handle: { partPath },
7188
- shapes: slide.shapes.map((shape) => withShapePartPath(shape, partPath))
7189
- };
7190
- }
7191
- function withShapePartPath(shape, partPath) {
7192
- if (shape.kind === "raw") return shape;
7193
- const handle = shape.handle === void 0 ? void 0 : { ...shape.handle, partPath };
7194
- if (shape.kind === "group") {
7195
- return {
7196
- ...shape,
7197
- ...handle !== void 0 ? { handle } : {},
7198
- children: shape.children.map((child) => withShapePartPath(child, partPath))
7199
- };
7200
- }
7201
- if (shape.kind !== "shape" || shape.textBody === void 0) {
7202
- return { ...shape, ...handle !== void 0 ? { handle } : {} };
7203
- }
7204
- return {
7205
- ...shape,
7206
- ...handle !== void 0 ? { handle } : {},
7207
- textBody: {
7208
- ...shape.textBody,
7209
- paragraphs: shape.textBody.paragraphs.map((paragraph) => ({
7210
- ...paragraph,
7211
- ...paragraph.handle !== void 0 ? { handle: { ...paragraph.handle, partPath } } : {},
7212
- runs: paragraph.runs.map((run) => ({
7213
- ...run,
7214
- ...run.handle !== void 0 ? { handle: { ...run.handle, partPath } } : {}
7215
- }))
7216
- }))
7217
- }
7218
- };
7219
- }
7220
- var EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS = {
7221
- bold: (value) => requireBooleanOrUndefined(value, "bold"),
7222
- italic: (value) => requireBooleanOrUndefined(value, "italic"),
7223
- underline: (value) => requireBooleanOrUndefined(value, "underline"),
7224
- fontSize: (value) => {
7225
- if (value !== void 0 && (!Number.isFinite(value) || value <= 0)) {
7226
- throw new Error("updateTextRunProperties: fontSize must be a finite positive pt value");
7227
- }
7228
- },
7229
- color: (value) => {
7230
- if (value === void 0) return;
7231
- if (value.kind !== "srgb") {
7232
- throw new Error("updateTextRunProperties: only srgb text run color is supported");
7233
- }
7234
- if (!/^[0-9A-Fa-f]{6}$/.test(value.hex)) {
7235
- throw new Error("updateTextRunProperties: srgb text run color must be a 6-digit hex value");
7236
- }
7237
- },
7238
- typeface: (value) => {
7239
- if (value !== void 0 && value.trim() === "") {
7240
- throw new Error("updateTextRunProperties: typeface must be a non-empty string");
7241
- }
7242
- }
7243
- };
7244
- var EDITABLE_TEXT_RUN_PROPERTIES = Object.keys(EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS).filter(
7245
- (property) => property in EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS
7246
- );
7247
- var EDITABLE_TEXT_RUN_PROPERTY_SET = new Set(EDITABLE_TEXT_RUN_PROPERTIES);
7248
- function replaceTextRunPlainText(source, handle, text) {
7249
- const result = mapMatchingTextRun(
7250
- source,
7251
- handle,
7252
- (run) => run.text === text ? run : { ...run, text }
7253
- );
7254
- if (!result.matched) {
7255
- throw new Error(
7256
- "replaceTextRunPlainText: text run handle was not found in PptxSourceModel source"
7257
- );
7258
- }
7259
- if (!result.changed) return source;
7260
- return {
7261
- ...source,
7262
- slides: result.slides,
7263
- edits: [...source.edits ?? [], { kind: "replaceTextRunPlainText", handle, text }]
7264
- };
7265
- }
7266
- function setTextRunProperties(source, handle, properties) {
7267
- return updateTextRunProperties(source, handle, {
7268
- set: properties,
7269
- clear: []
7270
- });
7271
- }
7272
- function clearTextRunProperties(source, handle, properties) {
7273
- return updateTextRunProperties(source, handle, {
7274
- set: {},
7275
- clear: properties
7276
- });
7277
- }
7278
- function replaceParagraphPlainText(source, handle, text) {
7279
- const result = mapMatchingParagraph(source, handle, (paragraph) => {
7280
- const replacementHandle = createReplacementRunHandle(paragraph);
7281
- return {
7282
- ...paragraph,
7283
- runs: [
7284
- {
7285
- kind: "textRun",
7286
- text,
7287
- ...paragraph.runs[0]?.properties !== void 0 ? { properties: paragraph.runs[0].properties } : {},
7288
- ...replacementHandle !== void 0 ? { handle: replacementHandle } : {}
7289
- }
7290
- ]
7291
- };
7292
- });
7293
- if (!result.matched) {
7294
- throw new Error(
7295
- "replaceParagraphPlainText: paragraph handle was not found in PptxSourceModel source"
7296
- );
7297
- }
7298
- return {
7299
- ...source,
7300
- slides: result.slides,
7301
- edits: [...source.edits ?? [], { kind: "replaceParagraphPlainText", handle, text }]
7302
- };
7303
- }
7304
- function updateTextRunProperties(source, handle, patch) {
7305
- assertEditableTextRunProperties(patch.set);
7306
- assertEditableTextRunPropertyNames(patch.clear);
7307
- const set = definedEditableTextRunProperties(patch.set);
7308
- if (Object.values(set).every((value) => value === void 0) && patch.clear.length === 0) {
7309
- throw new Error("updateTextRunProperties: patch must set or clear at least one property");
7310
- }
7311
- const result = mapMatchingTextRun(source, handle, (run) => {
7312
- const properties = patchTextRunProperties(run.properties, { set, clear: patch.clear });
7313
- if (textRunPropertiesEqual(run.properties, properties)) return run;
7314
- return {
7315
- kind: run.kind,
7316
- text: run.text,
7317
- ...run.handle !== void 0 ? { handle: run.handle } : {},
7318
- ...run.rawSidecars !== void 0 ? { rawSidecars: run.rawSidecars } : {},
7319
- ...properties !== void 0 ? { properties } : {}
7320
- };
7321
- });
7322
- if (!result.matched) {
7323
- throw new Error(
7324
- "updateTextRunProperties: text run handle was not found in PptxSourceModel source"
7325
- );
7326
- }
7327
- if (!result.changed) return source;
7328
- return {
7329
- ...source,
7330
- slides: result.slides,
7331
- edits: [
7332
- ...source.edits ?? [],
7333
- {
7334
- kind: "updateTextRunProperties",
7335
- handle,
7336
- ...Object.keys(set).length > 0 ? { set } : {},
7337
- ...patch.clear.length > 0 ? { clear: patch.clear } : {}
8240
+ slideRelationshipId: notesRelationship.id,
8241
+ newPartPath,
8242
+ contentType,
8243
+ raw,
8244
+ ...notesRelationships === void 0 ? {} : {
8245
+ relationships: {
8246
+ sourcePartPath: newPartPath,
8247
+ relationships: notesRelationships.relationships.map(
8248
+ (relationship) => relationship.type === SLIDE_REL_TYPE && relationship.targetMode !== "External" ? { ...relationship, target: relativeTarget(newPartPath, newSlidePartPath) } : relationship
8249
+ )
7338
8250
  }
7339
- ]
7340
- };
7341
- }
7342
- function mapMatchingTextRun(source, handle, mapRun) {
7343
- return mapTextBodyParagraphs(source, (paragraph) => {
7344
- let matched = false;
7345
- let changed = false;
7346
- const runs = paragraph.runs.map((run) => {
7347
- if (!sourceHandlesEqual(run.handle, handle)) return run;
7348
- matched = true;
7349
- const mapped = mapRun(run);
7350
- if (mapped === run) return run;
7351
- changed = true;
7352
- return mapped;
7353
- });
7354
- return {
7355
- paragraph: changed ? { ...paragraph, runs } : paragraph,
7356
- matched
7357
- };
7358
- });
7359
- }
7360
- function mapMatchingParagraph(source, handle, mapParagraph) {
7361
- return mapTextBodyParagraphs(source, (paragraph) => {
7362
- if (!sourceHandlesEqual(paragraph.handle, handle)) {
7363
- return { paragraph, matched: false };
7364
8251
  }
7365
- return { paragraph: mapParagraph(paragraph), matched: true };
7366
- });
8252
+ };
7367
8253
  }
7368
- function mapTextBodyParagraphs(source, mapParagraph) {
7369
- let matched = false;
7370
- let changed = false;
7371
- const slides = source.slides.map((slide) => {
7372
- let slideChanged = false;
7373
- const shapes = slide.shapes.map((shape) => {
7374
- if (shape.kind !== "shape" || shape.textBody === void 0) return shape;
7375
- let shapeChanged = false;
7376
- const paragraphs = shape.textBody.paragraphs.map((paragraph) => {
7377
- const result = mapParagraph(paragraph);
7378
- if (result.matched) matched = true;
7379
- if (result.paragraph === paragraph) return paragraph;
7380
- changed = true;
7381
- shapeChanged = true;
7382
- slideChanged = true;
7383
- return result.paragraph;
7384
- });
7385
- if (!shapeChanged) return shape;
7386
- return {
7387
- ...shape,
7388
- textBody: {
7389
- ...shape.textBody,
7390
- paragraphs
7391
- }
7392
- };
7393
- });
7394
- return slideChanged ? { ...slide, shapes } : slide;
7395
- });
8254
+ function withPartPath(slide, partPath) {
7396
8255
  return {
7397
- slides: changed ? slides : source.slides,
7398
- matched,
7399
- changed
8256
+ ...slide,
8257
+ partPath,
8258
+ handle: { partPath },
8259
+ shapes: slide.shapes.map((shape) => withShapePartPath(shape, partPath))
7400
8260
  };
7401
8261
  }
7402
- function patchTextRunProperties(current, patch) {
7403
- const next = { ...current ?? {} };
7404
- for (const property of patch.clear) {
7405
- delete next[property];
7406
- }
7407
- Object.assign(next, patch.set);
7408
- return Object.keys(next).length > 0 ? next : void 0;
7409
- }
7410
- function assertEditableTextRunProperties(properties) {
7411
- for (const property of Object.keys(properties)) {
7412
- assertEditableTextRunPropertyName(property);
7413
- }
7414
- for (const property of EDITABLE_TEXT_RUN_PROPERTIES) {
7415
- validateEditableTextRunProperty(property, properties[property]);
7416
- }
7417
- }
7418
- function requireBooleanOrUndefined(value, fieldName) {
7419
- if (value !== void 0 && typeof value !== "boolean") {
7420
- throw new Error(`updateTextRunProperties: ${fieldName} must be a boolean value`);
7421
- }
7422
- }
7423
- function assertEditableTextRunPropertyNames(properties) {
7424
- for (const property of properties) {
7425
- assertEditableTextRunPropertyName(property);
7426
- }
7427
- }
7428
- function definedEditableTextRunProperties(properties) {
7429
- const defined = {};
7430
- for (const property of EDITABLE_TEXT_RUN_PROPERTIES) {
7431
- copyDefinedEditableTextRunProperty(defined, properties, property);
7432
- }
7433
- return defined;
7434
- }
7435
- function assertEditableTextRunPropertyName(property) {
7436
- if (!isEditableTextRunProperty(property)) {
7437
- throw new Error(`updateTextRunProperties: unsupported text run property '${property}'`);
7438
- }
7439
- }
7440
- function isEditableTextRunProperty(property) {
7441
- return EDITABLE_TEXT_RUN_PROPERTY_SET.has(property);
7442
- }
7443
- function validateEditableTextRunProperty(property, value) {
7444
- EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS[property](value);
7445
- }
7446
- function copyDefinedEditableTextRunProperty(target, source, property) {
7447
- const value = source[property];
7448
- if (value !== void 0) {
7449
- target[property] = value;
7450
- }
7451
- }
7452
- function textRunPropertiesEqual(left, right) {
7453
- return stableValueEqual(left ?? {}, right ?? {});
7454
- }
7455
- function stableValueEqual(left, right) {
7456
- if (Object.is(left, right)) return true;
7457
- if (Array.isArray(left) || Array.isArray(right)) {
7458
- if (!Array.isArray(left) || !Array.isArray(right)) return false;
7459
- if (left.length !== right.length) return false;
7460
- return left.every((value, index) => stableValueEqual(value, right[index]));
8262
+ function withShapePartPath(shape, partPath) {
8263
+ if (shape.kind === "raw") return shape;
8264
+ const handle = shape.handle === void 0 ? void 0 : { ...shape.handle, partPath };
8265
+ if (shape.kind === "group") {
8266
+ return {
8267
+ ...shape,
8268
+ ...handle !== void 0 ? { handle } : {},
8269
+ children: shape.children.map((child) => withShapePartPath(child, partPath))
8270
+ };
7461
8271
  }
7462
- if (isPlainRecord(left) || isPlainRecord(right)) {
7463
- if (!isPlainRecord(left) || !isPlainRecord(right)) return false;
7464
- const leftKeys = Object.keys(left).sort();
7465
- const rightKeys = Object.keys(right).sort();
7466
- if (!stableValueEqual(leftKeys, rightKeys)) return false;
7467
- return leftKeys.every((key) => stableValueEqual(left[key], right[key]));
8272
+ if (shape.kind !== "shape" || shape.textBody === void 0) {
8273
+ return { ...shape, ...handle !== void 0 ? { handle } : {} };
7468
8274
  }
7469
- return false;
7470
- }
7471
- function isPlainRecord(value) {
7472
- return typeof value === "object" && value !== null && !Array.isArray(value);
7473
- }
7474
- function createReplacementRunHandle(paragraph) {
7475
- if (paragraph.runs[0]?.handle !== void 0) return paragraph.runs[0].handle;
7476
- if (paragraph.handle?.nodeId === void 0) return void 0;
7477
8275
  return {
7478
- ...paragraph.handle,
7479
- nodeId: asSourceNodeId(`${paragraph.handle.nodeId}:r:0`),
7480
- orderingSlot: 0
8276
+ ...shape,
8277
+ ...handle !== void 0 ? { handle } : {},
8278
+ textBody: {
8279
+ ...shape.textBody,
8280
+ paragraphs: shape.textBody.paragraphs.map((paragraph) => ({
8281
+ ...paragraph,
8282
+ ...paragraph.handle !== void 0 ? { handle: { ...paragraph.handle, partPath } } : {},
8283
+ runs: paragraph.runs.map((run) => ({
8284
+ ...run,
8285
+ ...run.handle !== void 0 ? { handle: { ...run.handle, partPath } } : {}
8286
+ }))
8287
+ }))
8288
+ }
7481
8289
  };
7482
8290
  }
7483
- function asEmu2(value) {
7484
- return unsafeBrandAssertion2(value);
7485
- }
7486
- function asPt(value) {
7487
- return unsafeBrandAssertion2(value);
7488
- }
7489
- function asHundredthPt2(value) {
7490
- return unsafeBrandAssertion2(value);
7491
- }
7492
- function asOoxmlPercent(value) {
7493
- return unsafeBrandAssertion2(value);
8291
+ function assertValidSlideIndex(index, slideCount, operationName) {
8292
+ if (!Number.isInteger(index) || index < 0 || index >= slideCount) {
8293
+ throw new Error(`${operationName}: toIndex must be an integer slide index in range`);
8294
+ }
7494
8295
  }
7495
- function asOoxmlAngle(value) {
7496
- return unsafeBrandAssertion2(value);
8296
+ function moveReadonly(items, fromIndex, toIndex) {
8297
+ const moved = [...items];
8298
+ const [item] = moved.splice(fromIndex, 1);
8299
+ if (item === void 0) return items;
8300
+ moved.splice(toIndex, 0, item);
8301
+ return moved;
7497
8302
  }
7498
- var RECTANGLE_ALIGNMENT_TOKENS = /* @__PURE__ */ new Set([
7499
- "tl",
7500
- "t",
7501
- "tr",
7502
- "l",
7503
- "ctr",
7504
- "r",
7505
- "bl",
7506
- "b",
7507
- "br"
7508
- ]);
7509
- var COLOR_TRANSFORM_KINDS = /* @__PURE__ */ new Set([
7510
- "lumMod",
7511
- "lumOff",
7512
- "tint",
7513
- "shade",
7514
- "alpha"
7515
- ]);
7516
- var RAW_FILL_LOCAL_NAMES = ["grpFill"];
7517
- var PRESET_COLOR_HEX = {
7518
- black: "000000",
7519
- white: "FFFFFF",
7520
- red: "FF0000",
7521
- green: "008000",
7522
- blue: "0000FF",
7523
- yellow: "FFFF00",
7524
- cyan: "00FFFF",
7525
- magenta: "FF00FF"
7526
- };
7527
- function parseColorElement(parent) {
7528
- if (!parent) return void 0;
7529
- const srgb = getChild(parent, "srgbClr");
7530
- if (srgb) {
7531
- const hex = getAttr(srgb, "val");
7532
- if (hex !== void 0) {
7533
- return withTransforms({ kind: "srgb", hex: hex.toUpperCase() }, srgb);
8303
+ var EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS = {
8304
+ bold: (value) => requireBooleanOrUndefined(value, "bold"),
8305
+ italic: (value) => requireBooleanOrUndefined(value, "italic"),
8306
+ underline: (value) => requireBooleanOrUndefined(value, "underline"),
8307
+ fontSize: (value) => {
8308
+ if (value !== void 0 && (!Number.isFinite(value) || value <= 0)) {
8309
+ throw new Error("updateTextRunProperties: fontSize must be a finite positive pt value");
7534
8310
  }
7535
- }
7536
- const scheme = getChild(parent, "schemeClr");
7537
- if (scheme) {
7538
- const name = getAttr(scheme, "val");
7539
- if (name !== void 0) {
7540
- return withTransforms({ kind: "scheme", scheme: name }, scheme);
8311
+ },
8312
+ color: (value) => {
8313
+ if (value === void 0) return;
8314
+ if (value.kind !== "srgb") {
8315
+ throw new Error("updateTextRunProperties: only srgb text run color is supported");
8316
+ }
8317
+ if (!/^[0-9A-Fa-f]{6}$/.test(value.hex)) {
8318
+ throw new Error("updateTextRunProperties: srgb text run color must be a 6-digit hex value");
8319
+ }
8320
+ },
8321
+ typeface: (value) => {
8322
+ if (value !== void 0 && value.trim() === "") {
8323
+ throw new Error("updateTextRunProperties: typeface must be a non-empty string");
7541
8324
  }
7542
8325
  }
7543
- const sys = getChild(parent, "sysClr");
7544
- if (sys) {
7545
- const val = getAttr(sys, "val");
7546
- if (val !== void 0) {
7547
- const lastClr = getAttr(sys, "lastClr");
7548
- return withTransforms(
7549
- {
7550
- kind: "system",
7551
- value: val,
7552
- ...lastClr !== void 0 ? { lastColor: lastClr.toUpperCase() } : {}
7553
- },
7554
- sys
7555
- );
7556
- }
8326
+ };
8327
+ var EDITABLE_TEXT_RUN_PROPERTIES = Object.keys(EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS).filter(
8328
+ (property) => property in EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS
8329
+ );
8330
+ var EDITABLE_TEXT_RUN_PROPERTY_SET = new Set(EDITABLE_TEXT_RUN_PROPERTIES);
8331
+ var EDITABLE_PARAGRAPH_PROPERTIES = [
8332
+ "align",
8333
+ "level",
8334
+ "bullet"
8335
+ ];
8336
+ var EDITABLE_PARAGRAPH_PROPERTY_SET = new Set(EDITABLE_PARAGRAPH_PROPERTIES);
8337
+ var TEXT_ALIGN_VALUES = /* @__PURE__ */ new Set([
8338
+ "left",
8339
+ "center",
8340
+ "right",
8341
+ "justify"
8342
+ ]);
8343
+ var AUTO_NUM_SCHEMES = /* @__PURE__ */ new Set([
8344
+ "arabicPeriod",
8345
+ "arabicParenR",
8346
+ "romanUcPeriod",
8347
+ "romanLcPeriod",
8348
+ "alphaUcPeriod",
8349
+ "alphaLcPeriod",
8350
+ "alphaLcParenR",
8351
+ "alphaUcParenR",
8352
+ "arabicPlain"
8353
+ ]);
8354
+ function replaceTextRunPlainText(source, handle, text) {
8355
+ const result = mapMatchingTextRun(
8356
+ source,
8357
+ handle,
8358
+ (run) => run.text === text ? run : { ...run, text }
8359
+ );
8360
+ if (!result.matched) {
8361
+ throw new Error(
8362
+ "replaceTextRunPlainText: text run handle was not found in PptxSourceModel source"
8363
+ );
7557
8364
  }
7558
- return void 0;
7559
- }
7560
- function parseEffectList(effectList) {
7561
- if (effectList === void 0) return void 0;
7562
- const outerShadow = parseOuterShadow(getChild(effectList, "outerShdw"));
7563
- const innerShadow = parseInnerShadow(getChild(effectList, "innerShdw"));
7564
- const glow = parseGlow(getChild(effectList, "glow"));
7565
- const softEdge = parseSoftEdge(getChild(effectList, "softEdge"));
7566
- const parsed = {
7567
- ...outerShadow !== void 0 ? { outerShadow } : {},
7568
- ...innerShadow !== void 0 ? { innerShadow } : {},
7569
- ...glow !== void 0 ? { glow } : {},
7570
- ...softEdge !== void 0 ? { softEdge } : {}
8365
+ if (!result.changed) return source;
8366
+ return {
8367
+ ...source,
8368
+ slides: result.slides,
8369
+ edits: [...source.edits ?? [], { kind: "replaceTextRunPlainText", handle, text }]
7571
8370
  };
7572
- return Object.keys(parsed).length > 0 ? parsed : void 0;
7573
8371
  }
7574
- function parseBlipEffects(blip) {
7575
- if (blip === void 0) return void 0;
7576
- const grayscale = getChild(blip, "grayscl") !== void 0;
7577
- const biLevel = parseBiLevel(getChild(blip, "biLevel"));
7578
- const blur = parseBlurEffect(getChild(blip, "blur"));
7579
- const lum = parseLumEffect(getChild(blip, "lum"));
7580
- const duotone = parseDuotoneEffect(getChild(blip, "duotone"));
7581
- const clrChange = parseColorChangeEffect(getChild(blip, "clrChange"));
7582
- const parsed = {
7583
- grayscale,
7584
- ...biLevel !== void 0 ? { biLevel } : {},
7585
- ...blur !== void 0 ? { blur } : {},
7586
- ...lum !== void 0 ? { lum } : {},
7587
- ...duotone !== void 0 ? { duotone } : {},
7588
- ...clrChange !== void 0 ? { clrChange } : {}
7589
- };
7590
- return grayscale || biLevel !== void 0 || blur !== void 0 || lum !== void 0 || duotone !== void 0 || clrChange !== void 0 ? parsed : void 0;
8372
+ function setTextRunProperties(source, handle, properties) {
8373
+ return updateTextRunProperties(source, handle, {
8374
+ set: properties,
8375
+ clear: []
8376
+ });
7591
8377
  }
7592
- function parseOuterShadow(node) {
7593
- if (node === void 0) return void 0;
7594
- const color = parseColorElement(node);
7595
- if (color === void 0) return void 0;
7596
- return {
7597
- blurRadius: asEmu2(numericAttr2(node, "blurRad") ?? 0),
7598
- distance: asEmu2(numericAttr2(node, "dist") ?? 0),
7599
- direction: asOoxmlAngle(numericAttr2(node, "dir") ?? 0),
7600
- color,
7601
- alignment: parseRectangleAlignment(getAttr(node, "algn"), "b"),
7602
- rotateWithShape: getAttr(node, "rotWithShape") !== "0"
7603
- };
8378
+ function clearTextRunProperties(source, handle, properties) {
8379
+ return updateTextRunProperties(source, handle, {
8380
+ set: {},
8381
+ clear: properties
8382
+ });
7604
8383
  }
7605
- function parseInnerShadow(node) {
7606
- if (node === void 0) return void 0;
7607
- const color = parseColorElement(node);
7608
- if (color === void 0) return void 0;
7609
- return {
7610
- blurRadius: asEmu2(numericAttr2(node, "blurRad") ?? 0),
7611
- distance: asEmu2(numericAttr2(node, "dist") ?? 0),
7612
- direction: asOoxmlAngle(numericAttr2(node, "dir") ?? 0),
7613
- color
7614
- };
8384
+ function setParagraphProperties(source, handle, properties) {
8385
+ return updateParagraphProperties(source, handle, {
8386
+ set: properties,
8387
+ clear: []
8388
+ });
7615
8389
  }
7616
- function parseGlow(node) {
7617
- if (node === void 0) return void 0;
7618
- const color = parseColorElement(node);
7619
- if (color === void 0) return void 0;
7620
- return {
7621
- radius: asEmu2(numericAttr2(node, "rad") ?? 0),
7622
- color
7623
- };
8390
+ function clearParagraphProperties(source, handle, properties) {
8391
+ return updateParagraphProperties(source, handle, {
8392
+ set: {},
8393
+ clear: properties
8394
+ });
7624
8395
  }
7625
- function parseSoftEdge(node) {
7626
- if (node === void 0) return void 0;
8396
+ function replaceParagraphPlainText(source, handle, text) {
8397
+ const result = mapMatchingParagraph(source, handle, (paragraph) => {
8398
+ const replacementHandle = createReplacementRunHandle(paragraph);
8399
+ return {
8400
+ ...paragraph,
8401
+ runs: [
8402
+ {
8403
+ kind: "textRun",
8404
+ text,
8405
+ ...paragraph.runs[0]?.properties !== void 0 ? { properties: paragraph.runs[0].properties } : {},
8406
+ ...replacementHandle !== void 0 ? { handle: replacementHandle } : {}
8407
+ }
8408
+ ]
8409
+ };
8410
+ });
8411
+ if (!result.matched) {
8412
+ throw new Error(
8413
+ "replaceParagraphPlainText: paragraph handle was not found in PptxSourceModel source"
8414
+ );
8415
+ }
7627
8416
  return {
7628
- radius: asEmu2(numericAttr2(node, "rad") ?? 0)
8417
+ ...source,
8418
+ slides: result.slides,
8419
+ edits: [...source.edits ?? [], { kind: "replaceParagraphPlainText", handle, text }]
7629
8420
  };
7630
8421
  }
7631
- function parseBiLevel(node) {
7632
- if (node === void 0) return void 0;
8422
+ function updateTextRunProperties(source, handle, patch) {
8423
+ assertEditableTextRunProperties(patch.set);
8424
+ assertEditableTextRunPropertyNames(patch.clear);
8425
+ const set = definedEditableTextRunProperties(patch.set);
8426
+ if (Object.values(set).every((value) => value === void 0) && patch.clear.length === 0) {
8427
+ throw new Error("updateTextRunProperties: patch must set or clear at least one property");
8428
+ }
8429
+ const result = mapMatchingTextRun(source, handle, (run) => {
8430
+ const properties = patchTextRunProperties(run.properties, { set, clear: patch.clear });
8431
+ if (textRunPropertiesEqual(run.properties, properties)) return run;
8432
+ return {
8433
+ kind: run.kind,
8434
+ text: run.text,
8435
+ ...run.handle !== void 0 ? { handle: run.handle } : {},
8436
+ ...run.rawSidecars !== void 0 ? { rawSidecars: run.rawSidecars } : {},
8437
+ ...properties !== void 0 ? { properties } : {}
8438
+ };
8439
+ });
8440
+ if (!result.matched) {
8441
+ throw new Error(
8442
+ "updateTextRunProperties: text run handle was not found in PptxSourceModel source"
8443
+ );
8444
+ }
8445
+ if (!result.changed) return source;
7633
8446
  return {
7634
- threshold: (numericAttr2(node, "thresh") ?? 5e4) / 1e5
8447
+ ...source,
8448
+ slides: result.slides,
8449
+ edits: [
8450
+ ...source.edits ?? [],
8451
+ {
8452
+ kind: "updateTextRunProperties",
8453
+ handle,
8454
+ ...Object.keys(set).length > 0 ? { set } : {},
8455
+ ...patch.clear.length > 0 ? { clear: patch.clear } : {}
8456
+ }
8457
+ ]
7635
8458
  };
7636
8459
  }
7637
- function parseBlurEffect(node) {
7638
- if (node === void 0) return void 0;
8460
+ function updateParagraphProperties(source, handle, patch) {
8461
+ assertEditableParagraphProperties(patch.set);
8462
+ assertEditableParagraphPropertyNames(patch.clear);
8463
+ const set = definedEditableParagraphProperties(patch.set);
8464
+ if (Object.values(set).every((value) => value === void 0) && patch.clear.length === 0) {
8465
+ throw new Error("updateParagraphProperties: patch must set or clear at least one property");
8466
+ }
8467
+ const result = mapMatchingParagraph(source, handle, (paragraph) => {
8468
+ const properties = patchParagraphProperties(paragraph.properties, { set, clear: patch.clear });
8469
+ if (paragraphPropertiesEqual(paragraph.properties, properties)) return paragraph;
8470
+ return {
8471
+ runs: paragraph.runs,
8472
+ ...paragraph.handle !== void 0 ? { handle: paragraph.handle } : {},
8473
+ ...paragraph.rawSidecars !== void 0 ? { rawSidecars: paragraph.rawSidecars } : {},
8474
+ ...properties !== void 0 ? { properties } : {}
8475
+ };
8476
+ });
8477
+ if (!result.matched) {
8478
+ throw new Error(
8479
+ "updateParagraphProperties: paragraph handle was not found in PptxSourceModel source"
8480
+ );
8481
+ }
8482
+ if (!result.changed) return source;
7639
8483
  return {
7640
- radius: asEmu2(numericAttr2(node, "rad") ?? 0),
7641
- grow: getAttr(node, "grow") !== "0"
8484
+ ...source,
8485
+ slides: result.slides,
8486
+ edits: [
8487
+ ...source.edits ?? [],
8488
+ {
8489
+ kind: "updateParagraphProperties",
8490
+ handle,
8491
+ ...Object.keys(set).length > 0 ? { set } : {},
8492
+ ...patch.clear.length > 0 ? { clear: patch.clear } : {}
8493
+ }
8494
+ ]
7642
8495
  };
7643
8496
  }
7644
- function parseLumEffect(node) {
7645
- if (node === void 0) return void 0;
8497
+ function mapMatchingTextRun(source, handle, mapRun) {
8498
+ return mapTextBodyParagraphs(source, (paragraph) => {
8499
+ let matched = false;
8500
+ let changed = false;
8501
+ const runs = paragraph.runs.map((run) => {
8502
+ if (!sourceHandlesEqual(run.handle, handle)) return run;
8503
+ matched = true;
8504
+ const mapped = mapRun(run);
8505
+ if (mapped === run) return run;
8506
+ changed = true;
8507
+ return mapped;
8508
+ });
8509
+ return {
8510
+ paragraph: changed ? { ...paragraph, runs } : paragraph,
8511
+ matched
8512
+ };
8513
+ });
8514
+ }
8515
+ function mapMatchingParagraph(source, handle, mapParagraph) {
8516
+ return mapTextBodyParagraphs(source, (paragraph) => {
8517
+ if (!sourceHandlesEqual(paragraph.handle, handle)) {
8518
+ return { paragraph, matched: false };
8519
+ }
8520
+ return { paragraph: mapParagraph(paragraph), matched: true };
8521
+ });
8522
+ }
8523
+ function mapTextBodyParagraphs(source, mapParagraph) {
8524
+ let matched = false;
8525
+ let changed = false;
8526
+ const slides = source.slides.map((slide) => {
8527
+ let slideChanged = false;
8528
+ const shapes = slide.shapes.map((shape) => {
8529
+ if (shape.kind !== "shape" || shape.textBody === void 0) return shape;
8530
+ let shapeChanged = false;
8531
+ const paragraphs = shape.textBody.paragraphs.map((paragraph) => {
8532
+ const result = mapParagraph(paragraph);
8533
+ if (result.matched) matched = true;
8534
+ if (result.paragraph === paragraph) return paragraph;
8535
+ changed = true;
8536
+ shapeChanged = true;
8537
+ slideChanged = true;
8538
+ return result.paragraph;
8539
+ });
8540
+ if (!shapeChanged) return shape;
8541
+ return {
8542
+ ...shape,
8543
+ textBody: {
8544
+ ...shape.textBody,
8545
+ paragraphs
8546
+ }
8547
+ };
8548
+ });
8549
+ return slideChanged ? { ...slide, shapes } : slide;
8550
+ });
7646
8551
  return {
7647
- brightness: (numericAttr2(node, "bright") ?? 0) / 1e5,
7648
- contrast: (numericAttr2(node, "contrast") ?? 0) / 1e5
8552
+ slides: changed ? slides : source.slides,
8553
+ matched,
8554
+ changed
7649
8555
  };
7650
8556
  }
7651
- function parseDuotoneEffect(node) {
7652
- if (node === void 0) return void 0;
7653
- const colors = collectColorChildren(node);
7654
- if (colors.length < 2) return void 0;
7655
- return { color1: colors[0], color2: colors[1] };
7656
- }
7657
- function parseColorChangeEffect(node) {
7658
- if (node === void 0) return void 0;
7659
- const from = firstColorChild(getChild(node, "clrFrom"));
7660
- const to = firstColorChild(getChild(node, "clrTo"));
7661
- return from !== void 0 && to !== void 0 ? { from, to } : void 0;
7662
- }
7663
- function collectColorChildren(parent) {
7664
- const colors = [];
7665
- for (const [key, value] of Object.entries(parent)) {
7666
- if (key.startsWith("@_")) continue;
7667
- const nodes = Array.isArray(value) ? value : [value];
7668
- for (const node of nodes) {
7669
- if (!isXmlNode(node)) continue;
7670
- const color = parseColorChild(key, node);
7671
- if (color !== void 0) colors.push(color);
7672
- }
8557
+ function patchTextRunProperties(current, patch) {
8558
+ const next = { ...current ?? {} };
8559
+ for (const property of patch.clear) {
8560
+ delete next[property];
7673
8561
  }
7674
- return colors;
7675
- }
7676
- function firstColorChild(parent) {
7677
- return parent !== void 0 ? collectColorChildren(parent)[0] : void 0;
7678
- }
7679
- function parseColorChild(key, node) {
7680
- const name = localName(key);
7681
- return name === "prstClr" ? parsePresetColor(node) : parseColorElement({ [name]: node });
7682
- }
7683
- function isXmlNode(value) {
7684
- return typeof value === "object" && value !== null;
7685
- }
7686
- function parsePresetColor(node) {
7687
- const value = getAttr(node, "val");
7688
- const hex = value !== void 0 ? PRESET_COLOR_HEX[value] : void 0;
7689
- return hex !== void 0 ? withTransforms({ kind: "srgb", hex }, node) : void 0;
8562
+ Object.assign(next, patch.set);
8563
+ return Object.keys(next).length > 0 ? next : void 0;
7690
8564
  }
7691
- function parseFill(parent, nextId) {
7692
- if (!parent) return void 0;
7693
- const solid = getChild(parent, "solidFill");
7694
- if (solid) {
7695
- const color = parseColorElement(solid);
7696
- if (color) return { kind: "solid", color };
7697
- return { kind: "raw", raw: makeSidecar("a:solidFill", solid, nextId) };
7698
- }
7699
- if (hasChild(parent, "noFill")) return { kind: "none" };
7700
- const grad = getChild(parent, "gradFill");
7701
- if (grad) {
7702
- const fill = parseGradientFill(grad);
7703
- return fill ?? { kind: "raw", raw: makeSidecar("a:gradFill", grad, nextId) };
8565
+ function patchParagraphProperties(current, patch) {
8566
+ const next = { ...current ?? {} };
8567
+ for (const property of patch.clear) {
8568
+ delete next[property];
7704
8569
  }
7705
- const blip = getChild(parent, "blipFill");
7706
- if (blip) {
7707
- return parseBlipFill(blip) ?? { kind: "raw", raw: makeSidecar("a:blipFill", blip, nextId) };
8570
+ Object.assign(next, patch.set);
8571
+ return Object.keys(next).length > 0 ? next : void 0;
8572
+ }
8573
+ function assertEditableTextRunProperties(properties) {
8574
+ for (const property of Object.keys(properties)) {
8575
+ assertEditableTextRunPropertyName(property);
7708
8576
  }
7709
- const pattern = getChild(parent, "pattFill");
7710
- if (pattern) {
7711
- const fill = parsePatternFill(pattern);
7712
- return fill ?? { kind: "raw", raw: makeSidecar("a:pattFill", pattern, nextId) };
8577
+ for (const property of EDITABLE_TEXT_RUN_PROPERTIES) {
8578
+ validateEditableTextRunProperty(property, properties[property]);
7713
8579
  }
7714
- for (const name of RAW_FILL_LOCAL_NAMES) {
7715
- if (hasChild(parent, name)) {
7716
- return { kind: "raw", raw: makeSidecar(`a:${name}`, getChild(parent, name) ?? {}, nextId) };
7717
- }
8580
+ }
8581
+ function assertEditableParagraphProperties(properties) {
8582
+ for (const property of Object.keys(properties)) {
8583
+ assertEditableParagraphPropertyName(property);
7718
8584
  }
7719
- return void 0;
8585
+ validateParagraphAlign(properties.align);
8586
+ validateParagraphLevel(properties.level);
8587
+ validateParagraphBullet(properties.bullet);
7720
8588
  }
7721
- function parseGradientFill(grad) {
7722
- const stops = [];
7723
- for (const gs of getChildArray(getChild(grad, "gsLst"), "gs")) {
7724
- const color = parseColorElement(gs);
7725
- if (color === void 0) continue;
7726
- stops.push({
7727
- position: (numericAttr2(gs, "pos") ?? 0) / 1e5,
7728
- color
7729
- });
8589
+ function requireBooleanOrUndefined(value, fieldName) {
8590
+ if (value !== void 0 && typeof value !== "boolean") {
8591
+ throw new Error(`updateTextRunProperties: ${fieldName} must be a boolean value`);
7730
8592
  }
7731
- if (stops.length === 0) return void 0;
7732
- const path = getChild(grad, "path");
7733
- if (path !== void 0) {
7734
- const fillToRect = getChild(path, "fillToRect");
7735
- const l = numericAttr2(fillToRect, "l") ?? 0;
7736
- const t = numericAttr2(fillToRect, "t") ?? 0;
7737
- const r = numericAttr2(fillToRect, "r") ?? 0;
7738
- const b = numericAttr2(fillToRect, "b") ?? 0;
7739
- return {
7740
- kind: "gradient",
7741
- gradientType: "radial",
7742
- stops,
7743
- centerX: (l + (1e5 - r)) / 2 / 1e5,
7744
- centerY: (t + (1e5 - b)) / 2 / 1e5
7745
- };
8593
+ }
8594
+ function assertEditableTextRunPropertyNames(properties) {
8595
+ for (const property of properties) {
8596
+ assertEditableTextRunPropertyName(property);
7746
8597
  }
7747
- return {
7748
- kind: "gradient",
7749
- gradientType: "linear",
7750
- stops,
7751
- angle: asOoxmlAngle(numericAttr2(getChild(grad, "lin"), "ang") ?? 0)
7752
- };
7753
8598
  }
7754
- function parseBlipFill(blipFill) {
7755
- const blip = getChild(blipFill, "blip");
7756
- const embed = getNamespacedAttr(blip, "embed");
7757
- if (embed === void 0) return void 0;
7758
- const tile = parseImageFillTile(getChild(blipFill, "tile"));
7759
- return {
7760
- kind: "image",
7761
- blipRelationshipId: asRelationshipId(embed),
7762
- ...tile !== void 0 ? { tile } : {}
7763
- };
8599
+ function assertEditableParagraphPropertyNames(properties) {
8600
+ for (const property of properties) {
8601
+ assertEditableParagraphPropertyName(property);
8602
+ }
7764
8603
  }
7765
- function parseImageFillTile(tile) {
7766
- if (tile === void 0) return void 0;
7767
- const flip = getAttr(tile, "flip") ?? "none";
7768
- return {
7769
- tx: asEmu2(numericAttr2(tile, "tx") ?? 0),
7770
- ty: asEmu2(numericAttr2(tile, "ty") ?? 0),
7771
- sx: (numericAttr2(tile, "sx") ?? 1e5) / 1e5,
7772
- sy: (numericAttr2(tile, "sy") ?? 1e5) / 1e5,
7773
- flip: flip === "x" || flip === "y" || flip === "xy" ? flip : "none",
7774
- align: parseRectangleAlignment(getAttr(tile, "algn"), "tl")
7775
- };
8604
+ function definedEditableTextRunProperties(properties) {
8605
+ const defined = {};
8606
+ for (const property of EDITABLE_TEXT_RUN_PROPERTIES) {
8607
+ copyDefinedEditableTextRunProperty(defined, properties, property);
8608
+ }
8609
+ return defined;
7776
8610
  }
7777
- function parseRectangleAlignment(value, fallback) {
7778
- return parseEnumValueWithDefault(value, RECTANGLE_ALIGNMENT_TOKENS, fallback);
8611
+ function definedEditableParagraphProperties(properties) {
8612
+ const defined = {};
8613
+ for (const property of EDITABLE_PARAGRAPH_PROPERTIES) {
8614
+ copyDefinedEditableParagraphProperty(defined, properties, property);
8615
+ }
8616
+ return defined;
7779
8617
  }
7780
- function parsePatternFill(pattern) {
7781
- const foregroundColor = parseColorElement(getChild(pattern, "fgClr"));
7782
- const backgroundColor = parseColorElement(getChild(pattern, "bgClr"));
7783
- if (foregroundColor === void 0 || backgroundColor === void 0) return void 0;
7784
- return {
7785
- kind: "pattern",
7786
- preset: getAttr(pattern, "prst") ?? "ltDnDiag",
7787
- foregroundColor,
7788
- backgroundColor
7789
- };
8618
+ function assertEditableTextRunPropertyName(property) {
8619
+ if (!isEditableTextRunProperty(property)) {
8620
+ throw new Error(`updateTextRunProperties: unsupported text run property '${property}'`);
8621
+ }
7790
8622
  }
7791
- function parseOutline(spPr, nextId) {
7792
- const ln = getChild(spPr, "ln");
7793
- return parseLine(ln, nextId);
8623
+ function assertEditableParagraphPropertyName(property) {
8624
+ if (!EDITABLE_PARAGRAPH_PROPERTY_SET.has(property)) {
8625
+ throw new Error(`updateParagraphProperties: unsupported paragraph property '${property}'`);
8626
+ }
7794
8627
  }
7795
- function parseLine(ln, nextId) {
7796
- if (!ln) return void 0;
7797
- const width = numericAttr2(ln, "w");
7798
- const fill = parseFill(ln, nextId);
7799
- const dashStyle = parseDashStyle(getChild(ln, "prstDash"));
7800
- const customDash = parseCustomDash(ln);
7801
- const lineCap = parseLineCap(getAttr(ln, "cap"));
7802
- const lineJoin = parseLineJoin(ln);
7803
- const headEnd = parseArrowEndpoint(getChild(ln, "headEnd"));
7804
- const tailEnd = parseArrowEndpoint(getChild(ln, "tailEnd"));
7805
- return {
7806
- ...width !== void 0 ? { width: asEmu2(width) } : {},
7807
- ...fill !== void 0 ? { fill } : {},
7808
- ...dashStyle !== void 0 ? { dashStyle } : {},
7809
- ...customDash !== void 0 ? { customDash } : {},
7810
- ...lineCap !== void 0 ? { lineCap } : {},
7811
- ...lineJoin !== void 0 ? { lineJoin } : {},
7812
- ...headEnd !== void 0 ? { headEnd } : {},
7813
- ...tailEnd !== void 0 ? { tailEnd } : {}
7814
- };
8628
+ function isEditableTextRunProperty(property) {
8629
+ return EDITABLE_TEXT_RUN_PROPERTY_SET.has(property);
7815
8630
  }
7816
- function parseTransform(spPr) {
7817
- const xfrm = getChild(spPr, "xfrm");
7818
- if (!xfrm) return void 0;
7819
- const off = getChild(xfrm, "off");
7820
- const ext = getChild(xfrm, "ext");
7821
- const offsetX = numericAttr2(off, "x");
7822
- const offsetY = numericAttr2(off, "y");
7823
- const width = numericAttr2(ext, "cx");
7824
- const height = numericAttr2(ext, "cy");
7825
- if (offsetX === void 0 || offsetY === void 0 || width === void 0 || height === void 0) {
7826
- return void 0;
8631
+ function validateParagraphAlign(value) {
8632
+ if (value !== void 0 && !TEXT_ALIGN_VALUES.has(value)) {
8633
+ throw new Error("updateParagraphProperties: align must be left, center, right, or justify");
7827
8634
  }
7828
- const rotation = numericAttr2(xfrm, "rot");
7829
- const flipH = getAttr(xfrm, "flipH");
7830
- const flipV = getAttr(xfrm, "flipV");
7831
- return {
7832
- offsetX: asEmu2(offsetX),
7833
- offsetY: asEmu2(offsetY),
7834
- width: asEmu2(width),
7835
- height: asEmu2(height),
7836
- ...rotation !== void 0 ? { rotation: asOoxmlAngle(rotation) } : {},
7837
- ...isTrue(flipH) ? { flipHorizontal: true } : {},
7838
- ...isTrue(flipV) ? { flipVertical: true } : {}
7839
- };
7840
- }
7841
- function withTransforms(base, colorNode) {
7842
- const transforms = [];
7843
- for (const key of Object.keys(colorNode)) {
7844
- if (key.startsWith("@_")) continue;
7845
- const kind = localName(key);
7846
- const transformKind = parseEnumValue(kind, COLOR_TRANSFORM_KINDS);
7847
- if (transformKind === void 0) continue;
7848
- const value = colorNode[key];
7849
- const items = Array.isArray(value) ? value : [value];
7850
- for (const item of items) {
7851
- const raw = getAttr(unsafeOoxmlBoundaryAssertion(item), "val");
7852
- if (raw === void 0) continue;
7853
- const numeric = Number(raw);
7854
- if (!Number.isFinite(numeric)) continue;
7855
- transforms.push({
7856
- kind: transformKind,
7857
- value: asOoxmlPercent(numeric)
7858
- });
8635
+ }
8636
+ function validateParagraphLevel(value) {
8637
+ if (value !== void 0 && (!Number.isInteger(value) || value < 0 || value > 8)) {
8638
+ throw new Error("updateParagraphProperties: level must be an integer from 0 to 8");
8639
+ }
8640
+ }
8641
+ function validateParagraphBullet(value) {
8642
+ if (value === void 0) return;
8643
+ if (value.type === "none") return;
8644
+ if (value.type === "char") {
8645
+ if (typeof value.char !== "string" || value.char.length === 0) {
8646
+ throw new Error("updateParagraphProperties: bullet.char must be a non-empty string");
7859
8647
  }
8648
+ return;
7860
8649
  }
7861
- return transforms.length > 0 ? { ...base, transforms } : base;
8650
+ if (value.type === "autoNum") {
8651
+ if (!AUTO_NUM_SCHEMES.has(value.scheme)) {
8652
+ throw new Error("updateParagraphProperties: unsupported bullet auto-numbering scheme");
8653
+ }
8654
+ if (!Number.isInteger(value.startAt) || value.startAt < 1) {
8655
+ throw new Error("updateParagraphProperties: bullet.startAt must be a positive integer");
8656
+ }
8657
+ return;
8658
+ }
8659
+ throw new Error("updateParagraphProperties: unsupported bullet type");
7862
8660
  }
7863
- function numericAttr2(node, name) {
7864
- const raw = getAttr(node, name);
7865
- if (raw === void 0) return void 0;
7866
- const value = Number(raw);
7867
- return Number.isFinite(value) ? value : void 0;
8661
+ function validateEditableTextRunProperty(property, value) {
8662
+ EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS[property](value);
7868
8663
  }
7869
- function isTrue(value) {
7870
- return value === "1" || value === "true";
8664
+ function copyDefinedEditableParagraphProperty(target, source, property) {
8665
+ const value = source[property];
8666
+ if (value !== void 0) {
8667
+ target[property] = value;
8668
+ }
7871
8669
  }
7872
- function parseDashStyle(prstDash) {
7873
- const value = getAttr(prstDash, "val");
7874
- return parseEnumValue(value, DASH_STYLES);
8670
+ function copyDefinedEditableTextRunProperty(target, source, property) {
8671
+ const value = source[property];
8672
+ if (value !== void 0) {
8673
+ target[property] = value;
8674
+ }
7875
8675
  }
7876
- function parseCustomDash(ln) {
7877
- const custDash = getChild(ln, "custDash");
7878
- const segments = getChildArray(custDash, "ds");
7879
- if (segments.length === 0) return void 0;
7880
- return segments.flatMap((segment) => [
7881
- (numericAttr2(segment, "d") ?? 1e5) / 1e5,
7882
- (numericAttr2(segment, "sp") ?? 1e5) / 1e5
7883
- ]);
8676
+ function textRunPropertiesEqual(left, right) {
8677
+ return stableValueEqual2(left ?? {}, right ?? {});
7884
8678
  }
7885
- var LINE_CAP_MAP = {
7886
- flat: "butt",
7887
- sq: "square",
7888
- rnd: "round"
7889
- };
7890
- function parseLineCap(value) {
7891
- return value !== void 0 ? LINE_CAP_MAP[value] : void 0;
8679
+ function paragraphPropertiesEqual(left, right) {
8680
+ return stableValueEqual2(left ?? {}, right ?? {});
7892
8681
  }
7893
- function parseLineJoin(ln) {
7894
- if (hasChild(ln, "round")) return "round";
7895
- if (hasChild(ln, "bevel")) return "bevel";
7896
- if (hasChild(ln, "miter")) return "miter";
7897
- return void 0;
8682
+ function stableValueEqual2(left, right) {
8683
+ if (Object.is(left, right)) return true;
8684
+ if (Array.isArray(left) || Array.isArray(right)) {
8685
+ if (!Array.isArray(left) || !Array.isArray(right)) return false;
8686
+ if (left.length !== right.length) return false;
8687
+ return left.every((value, index) => stableValueEqual2(value, right[index]));
8688
+ }
8689
+ if (isPlainRecord2(left) || isPlainRecord2(right)) {
8690
+ if (!isPlainRecord2(left) || !isPlainRecord2(right)) return false;
8691
+ const leftKeys = Object.keys(left).sort();
8692
+ const rightKeys = Object.keys(right).sort();
8693
+ if (!stableValueEqual2(leftKeys, rightKeys)) return false;
8694
+ return leftKeys.every((key) => stableValueEqual2(left[key], right[key]));
8695
+ }
8696
+ return false;
7898
8697
  }
7899
- function parseArrowEndpoint(node) {
7900
- if (!node) return void 0;
7901
- const type = parseEnumValue(getAttr(node, "type"), ARROW_TYPES2);
7902
- if (type === void 0) return void 0;
7903
- const width = getAttr(node, "w") ?? "med";
7904
- const length = getAttr(node, "len") ?? "med";
8698
+ function isPlainRecord2(value) {
8699
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8700
+ }
8701
+ function createReplacementRunHandle(paragraph) {
8702
+ if (paragraph.runs[0]?.handle !== void 0) return paragraph.runs[0].handle;
8703
+ if (paragraph.handle?.nodeId === void 0) return void 0;
7905
8704
  return {
7906
- type,
7907
- width: parseEnumValueWithDefault(width, ARROW_SIZES2, "med"),
7908
- length: parseEnumValueWithDefault(length, ARROW_SIZES2, "med")
8705
+ ...paragraph.handle,
8706
+ nodeId: asSourceNodeId(`${paragraph.handle.nodeId}:r:0`),
8707
+ orderingSlot: 0
7909
8708
  };
7910
8709
  }
7911
- var DASH_STYLES = /* @__PURE__ */ new Set([
7912
- "solid",
7913
- "dash",
7914
- "dot",
7915
- "dashDot",
7916
- "lgDash",
7917
- "lgDashDot",
7918
- "sysDash",
7919
- "sysDot"
7920
- ]);
7921
- var ARROW_TYPES2 = /* @__PURE__ */ new Set([
7922
- "triangle",
7923
- "stealth",
7924
- "diamond",
7925
- "oval",
7926
- "arrow"
7927
- ]);
7928
- var ARROW_SIZES2 = /* @__PURE__ */ new Set(["sm", "med", "lg"]);
8710
+ function asEmu2(value) {
8711
+ return unsafeBrandAssertion2(value);
8712
+ }
8713
+ function asPt(value) {
8714
+ return unsafeBrandAssertion2(value);
8715
+ }
8716
+ function asHundredthPt2(value) {
8717
+ return unsafeBrandAssertion2(value);
8718
+ }
8719
+ function asOoxmlPercent(value) {
8720
+ return unsafeBrandAssertion2(value);
8721
+ }
8722
+ function asOoxmlAngle(value) {
8723
+ return unsafeBrandAssertion2(value);
8724
+ }
8725
+ var textEncoder = new TextEncoder();
8726
+ var ROOT_PART = asPartPath("");
8727
+ var PRESENTATION_PART = asPartPath("ppt/presentation.xml");
8728
+ var SLIDE_PART = asPartPath("ppt/slides/slide1.xml");
8729
+ var SLIDE_LAYOUT_PART = asPartPath("ppt/slideLayouts/slideLayout1.xml");
8730
+ var SLIDE_MASTER_PART = asPartPath("ppt/slideMasters/slideMaster1.xml");
8731
+ var THEME_PART = asPartPath("ppt/theme/theme1.xml");
8732
+ var APP_PROPS_PART = asPartPath("docProps/app.xml");
8733
+ var CORE_PROPS_PART = asPartPath("docProps/core.xml");
7929
8734
  var DEFAULT_COLOR_MAP = {
7930
8735
  bg1: "lt1",
7931
8736
  tx1: "dk1",
@@ -8489,7 +9294,7 @@ function computeConnectorElement(context, connector, layer, partPath) {
8489
9294
  sourceNode: connector,
8490
9295
  ...connector.transform !== void 0 ? { transform: connector.transform } : {},
8491
9296
  ...connector.geometry !== void 0 ? { geometry: connector.geometry } : {},
8492
- ...connector.outline !== void 0 ? { outline: computeOutline(context, connector.outline, partPath) } : connector.style?.lineRef !== void 0 ? { outline: resolveLineReference(context, connector.style.lineRef, partPath) } : {},
9297
+ ...computedOutlineProperty(context, connector.outline, connector.style?.lineRef, partPath),
8493
9298
  ...effects !== void 0 ? { effects } : {}
8494
9299
  };
8495
9300
  }
@@ -8533,7 +9338,7 @@ function computeShapeElement(context, shape, layer, partPath) {
8533
9338
  ...transform !== void 0 ? { transform } : {},
8534
9339
  ...geometry !== void 0 ? { geometry } : {},
8535
9340
  ...shape.fill !== void 0 ? { fill: computeFill(context, shape.fill, partPath) } : shape.style?.fillRef !== void 0 ? { fill: resolveFillReference(context, shape.style.fillRef, partPath) } : {},
8536
- ...shape.outline !== void 0 ? { outline: computeOutline(context, shape.outline, partPath) } : shape.style?.lineRef !== void 0 ? { outline: resolveLineReference(context, shape.style.lineRef, partPath) } : {},
9341
+ ...computedOutlineProperty(context, shape.outline, shape.style?.lineRef, partPath),
8537
9342
  ...effects !== void 0 ? { effects } : {},
8538
9343
  ...shape.textBody !== void 0 ? {
8539
9344
  textBody: computeTextBody(
@@ -8548,7 +9353,7 @@ function computeShapeElement(context, shape, layer, partPath) {
8548
9353
  }
8549
9354
  function computeImageElement(context, image, layer, partPath) {
8550
9355
  const relationship = resolveComputedRelationships(context.source, partPath).find(
8551
- (rel) => rel.id === image.blipRelationshipId && rel.type === IMAGE_REL_TYPE2
9356
+ (rel2) => rel2.id === image.blipRelationshipId && rel2.type === IMAGE_REL_TYPE2
8552
9357
  );
8553
9358
  const effects = image.effects !== void 0 ? computeEffectList(context, image.effects) : void 0;
8554
9359
  const blipEffects = image.blipEffects !== void 0 ? computeBlipEffects(context, image.blipEffects) : void 0;
@@ -8579,7 +9384,7 @@ function computeTableElement(context, table, layer, partPath) {
8579
9384
  }
8580
9385
  function computeChartElement(context, chart, layer, partPath) {
8581
9386
  const relationship = context.relationships.find(
8582
- (rel) => rel.id === chart.chartRelationshipId && CHART_REL_TYPES.has(rel.type)
9387
+ (rel2) => rel2.id === chart.chartRelationshipId && CHART_REL_TYPES.has(rel2.type)
8583
9388
  );
8584
9389
  const chartXml = relationship?.targetPartPath !== void 0 ? readRawPackageText(context.source, relationship.targetPartPath) : void 0;
8585
9390
  const chartData = chartXml !== void 0 ? parseComputedChartData(chartXml, context) : void 0;
@@ -8596,11 +9401,11 @@ function computeChartElement(context, chart, layer, partPath) {
8596
9401
  }
8597
9402
  function computeSmartArtElement(context, smartArt, layer, partPath) {
8598
9403
  const dataRelationship = context.relationships.find(
8599
- (rel) => rel.id === smartArt.dataRelationshipId && DIAGRAM_DATA_REL_TYPES.has(rel.type)
9404
+ (rel2) => rel2.id === smartArt.dataRelationshipId && DIAGRAM_DATA_REL_TYPES.has(rel2.type)
8600
9405
  );
8601
9406
  const dataRelationships = dataRelationship?.targetPartPath !== void 0 ? resolveComputedRelationships(context.source, dataRelationship.targetPartPath) : [];
8602
9407
  const drawingRelationship = dataRelationships.find(
8603
- (rel) => DIAGRAM_DRAWING_REL_TYPES.has(rel.type)
9408
+ (rel2) => DIAGRAM_DRAWING_REL_TYPES.has(rel2.type)
8604
9409
  );
8605
9410
  const drawingPartPath = drawingRelationship?.targetPartPath;
8606
9411
  const drawingXml = drawingPartPath !== void 0 ? readRawPackageText(context.source, drawingPartPath) : void 0;
@@ -8746,7 +9551,7 @@ function computeFill(context, fill, partPath) {
8746
9551
  };
8747
9552
  case "image": {
8748
9553
  const relationship = resolveComputedRelationships(context.source, partPath).find(
8749
- (rel) => rel.id === fill.blipRelationshipId && rel.type === IMAGE_REL_TYPE2
9554
+ (rel2) => rel2.id === fill.blipRelationshipId && rel2.type === IMAGE_REL_TYPE2
8750
9555
  );
8751
9556
  return {
8752
9557
  kind: "image",
@@ -8771,6 +9576,24 @@ function computeOutline(context, outline, partPath) {
8771
9576
  ...outline.fill !== void 0 ? { fill: computeFill(context, outline.fill, partPath) } : {}
8772
9577
  };
8773
9578
  }
9579
+ function computedOutlineProperty(context, outline, lineRef, partPath) {
9580
+ const styleOutline = lineRef !== void 0 ? resolveLineReference(context, lineRef, partPath) : void 0;
9581
+ if (outline === void 0) {
9582
+ return styleOutline !== void 0 ? { outline: styleOutline } : {};
9583
+ }
9584
+ const computed = mergeComputedOutline(styleOutline, computeOutline(context, outline, partPath));
9585
+ return { outline: computed };
9586
+ }
9587
+ function mergeComputedOutline(base, override) {
9588
+ if (base === void 0) return override;
9589
+ const width = override.width ?? base.width;
9590
+ const fill = override.fill ?? base.fill;
9591
+ return {
9592
+ source: { ...base.source, ...override.source },
9593
+ ...width !== void 0 ? { width } : {},
9594
+ ...fill !== void 0 ? { fill } : {}
9595
+ };
9596
+ }
8774
9597
  function resolveFillReference(context, ref, partPath) {
8775
9598
  if (ref.index === 0) return void 0;
8776
9599
  const list = ref.index >= 1e3 ? context.theme?.formatScheme?.backgroundFillStyles : context.theme?.formatScheme?.fillStyles;
@@ -9359,7 +10182,7 @@ var SLIDE_REL_TYPE2 = "http://schemas.openxmlformats.org/officeDocument/2006/rel
9359
10182
  var SLIDE_LAYOUT_REL_TYPE2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout";
9360
10183
  var SLIDE_MASTER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster";
9361
10184
  var THEME_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
9362
- var PRESENTATION_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
10185
+ var PRESENTATION_CONTENT_TYPE2 = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
9363
10186
  var textDecoder3 = new TextDecoder();
9364
10187
  function readPptx(input) {
9365
10188
  const entries = unzipPackage(input);
@@ -9526,15 +10349,15 @@ function parsePartRoot(entries, partPath, rootLocalName, diagnostics, includeOrd
9526
10349
  return { root, orderedRoot };
9527
10350
  }
9528
10351
  function resolveSingleRel(relationships, sourcePart, relType) {
9529
- const rels = relationships.find((rel) => rel.sourcePartPath === sourcePart)?.relationships;
9530
- const match = rels?.find((rel) => rel.type === relType && rel.targetMode !== "External");
10352
+ const rels = relationships.find((rel2) => rel2.sourcePartPath === sourcePart)?.relationships;
10353
+ const match = rels?.find((rel2) => rel2.type === relType && rel2.targetMode !== "External");
9531
10354
  if (match === void 0) return void 0;
9532
10355
  return resolveInternalRelationshipTarget(sourcePart, match);
9533
10356
  }
9534
10357
  function resolveAllRels(relationships, sourcePart, relType) {
9535
- const rels = relationships.find((rel) => rel.sourcePartPath === sourcePart)?.relationships ?? [];
9536
- return rels.filter((rel) => rel.type === relType && rel.targetMode !== "External").flatMap((rel) => {
9537
- const target = resolveInternalRelationshipTarget(sourcePart, rel);
10358
+ const rels = relationships.find((rel2) => rel2.sourcePartPath === sourcePart)?.relationships ?? [];
10359
+ return rels.filter((rel2) => rel2.type === relType && rel2.targetMode !== "External").flatMap((rel2) => {
10360
+ const target = resolveInternalRelationshipTarget(sourcePart, rel2);
9538
10361
  return target === void 0 ? [] : [target];
9539
10362
  });
9540
10363
  }
@@ -9623,7 +10446,7 @@ function readPresentation(entries, relationships, overrides, diagnostics) {
9623
10446
  const slideSize = readSlideSize(root);
9624
10447
  const defaultTextStyle = parseTextStyle(getChild(root, "defaultTextStyle"));
9625
10448
  const presentationRels = relationships.find(
9626
- (rel) => rel.sourcePartPath === presentationPath
10449
+ (rel2) => rel2.sourcePartPath === presentationPath
9627
10450
  )?.relationships;
9628
10451
  const slidePartPaths = [];
9629
10452
  const sldIdLst = getChild(root, "sldIdLst");
@@ -9631,7 +10454,7 @@ function readPresentation(entries, relationships, overrides, diagnostics) {
9631
10454
  const relId = getNamespacedAttr(sldId, "id");
9632
10455
  if (relId === void 0) continue;
9633
10456
  const handle = { partPath: presentationPartPath, relationshipId: asRelationshipId(relId) };
9634
- const relationship = presentationRels?.find((rel) => rel.id === relId);
10457
+ const relationship = presentationRels?.find((rel2) => rel2.id === relId);
9635
10458
  if (relationship === void 0) {
9636
10459
  diagnostics.push({
9637
10460
  severity: "warning",
@@ -9674,15 +10497,15 @@ function readSlideSize(presentationRoot) {
9674
10497
  }
9675
10498
  function locatePresentationPart(relationships, overrides) {
9676
10499
  const rootRels = relationships.find(
9677
- (rel) => rel.sourcePartPath === PACKAGE_ROOT_PART
10500
+ (rel2) => rel2.sourcePartPath === PACKAGE_ROOT_PART
9678
10501
  )?.relationships;
9679
10502
  const officeDocumentRel = rootRels?.find(
9680
- (rel) => rel.type === OFFICE_DOCUMENT_REL_TYPE && rel.targetMode !== "External"
10503
+ (rel2) => rel2.type === OFFICE_DOCUMENT_REL_TYPE && rel2.targetMode !== "External"
9681
10504
  );
9682
10505
  if (officeDocumentRel !== void 0) {
9683
10506
  return resolveRelationshipTarget(PACKAGE_ROOT_PART, officeDocumentRel.target);
9684
10507
  }
9685
- const override = overrides.find((entry) => entry.contentType === PRESENTATION_CONTENT_TYPE);
10508
+ const override = overrides.find((entry) => entry.contentType === PRESENTATION_CONTENT_TYPE2);
9686
10509
  return override?.partName;
9687
10510
  }
9688
10511
  var MEDIA_CONTENT_TYPE_PREFIXES = ["image/", "audio/", "video/"];
@@ -9710,9 +10533,9 @@ function extensionOf(path) {
9710
10533
  function stripLeadingSlash(path) {
9711
10534
  return path.startsWith("/") ? path.slice(1) : path;
9712
10535
  }
9713
- function parseShapeLocator(handle) {
10536
+ function parseShapeLocator(handle, editName = "shape edit") {
9714
10537
  if (handle.nodeId !== void 0) return { nodeId: String(handle.nodeId) };
9715
- throw new Error("writePptx: shape transform edit requires nodeId in handle");
10538
+ throw new Error(`writePptx: ${editName} requires nodeId in handle`);
9716
10539
  }
9717
10540
  function parseTextRunLocator(nodeId) {
9718
10541
  const value = String(nodeId ?? "");
@@ -9779,19 +10602,21 @@ function locateShapeTreeNode(spTree, locator) {
9779
10602
  function deleteShapeXml(spTree, nodeId) {
9780
10603
  if (spTree === void 0) return false;
9781
10604
  const entry = Object.entries(spTree).find(
9782
- ([key2]) => !key2.startsWith("@_") && localName(key2) === "sp"
10605
+ ([key2, value2]) => !key2.startsWith("@_") && (localName(key2) === "sp" || localName(key2) === "cxnSp") && getShapeTreeNodes(value2).some((shape) => getShapeTreeNodeId(shape) === nodeId)
9783
10606
  );
9784
10607
  if (entry === void 0) return false;
9785
10608
  const [key, value] = entry;
9786
- const shapes = Array.isArray(value) ? unsafeOoxmlBoundaryAssertion(value) : [value];
9787
- const nextShapes = shapes.filter(
9788
- (shape) => getShapeTreeNodeId(unsafeOoxmlBoundaryAssertion(shape)) !== nodeId
9789
- );
10609
+ const shapes = getShapeTreeNodes(value);
10610
+ const nextShapes = shapes.filter((shape) => getShapeTreeNodeId(shape) !== nodeId);
9790
10611
  if (nextShapes.length === shapes.length) return false;
9791
10612
  if (nextShapes.length === 0) delete spTree[key];
9792
10613
  else spTree[key] = Array.isArray(value) ? nextShapes : nextShapes[0];
9793
10614
  return true;
9794
10615
  }
10616
+ function getShapeTreeNodes(value) {
10617
+ const items = Array.isArray(value) ? unsafeOoxmlBoundaryAssertion(value) : [value];
10618
+ return items.map((item) => unsafeOoxmlBoundaryAssertion(item));
10619
+ }
9795
10620
  function getShapeByOrderingSlot(spTree, orderingSlot) {
9796
10621
  if (!spTree) return void 0;
9797
10622
  let currentSlot = 0;
@@ -9930,7 +10755,7 @@ function textRequiresPreserve(text) {
9930
10755
  return text.startsWith(" ") || text.endsWith(" ");
9931
10756
  }
9932
10757
  var XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
9933
- var textEncoder = new TextEncoder();
10758
+ var textEncoder2 = new TextEncoder();
9934
10759
  var textDecoder4 = new TextDecoder();
9935
10760
  var xmlBuilder2 = new XMLBuilder2({
9936
10761
  ignoreAttributes: false,
@@ -9939,8 +10764,16 @@ var xmlBuilder2 = new XMLBuilder2({
9939
10764
  suppressEmptyNode: true
9940
10765
  });
9941
10766
  function encodeXml(xml) {
9942
- return textEncoder.encode(xml);
10767
+ return textEncoder2.encode(xml);
9943
10768
  }
10769
+ var FILL_CHILD_LOCAL_NAMES = /* @__PURE__ */ new Set([
10770
+ "noFill",
10771
+ "solidFill",
10772
+ "gradFill",
10773
+ "blipFill",
10774
+ "pattFill",
10775
+ "grpFill"
10776
+ ]);
9944
10777
  function serializeDirtyXmlPart(source, partPath, edits) {
9945
10778
  const rawPart = source.packageGraph.rawParts?.find((part) => part.partPath === partPath);
9946
10779
  if (rawPart === void 0) {
@@ -9964,12 +10797,21 @@ function applyDirtyPartEdit(root, edit) {
9964
10797
  case "updateTextRunProperties":
9965
10798
  applyTextRunPropertiesEdit(root, edit);
9966
10799
  return;
10800
+ case "updateParagraphProperties":
10801
+ applyParagraphPropertiesEdit(root, edit);
10802
+ return;
9967
10803
  case "replaceParagraphPlainText":
9968
10804
  applyParagraphTextEdit(root, edit);
9969
10805
  return;
9970
10806
  case "updateShapeTransform":
9971
10807
  applyShapeTransformEdit(root, edit);
9972
10808
  return;
10809
+ case "updateShapeFill":
10810
+ applyShapeFillEdit(root, edit);
10811
+ return;
10812
+ case "updateShapeOutline":
10813
+ applyShapeOutlineEdit(root, edit);
10814
+ return;
9973
10815
  case "addTextBox":
9974
10816
  applyAddTextBoxEdit(root, edit);
9975
10817
  return;
@@ -9982,6 +10824,7 @@ function applyDirtyPartEdit(root, edit) {
9982
10824
  case "replaceImage":
9983
10825
  case "addEmptySlideFromLayout":
9984
10826
  case "duplicateSlide":
10827
+ case "moveSlide":
9985
10828
  case "deleteSlide":
9986
10829
  throw new Error(`writePptx: edit kind '${edit.kind}' does not patch a dirty XML part`);
9987
10830
  }
@@ -10048,6 +10891,34 @@ function applyParagraphTextEdit(root, edit) {
10048
10891
  }
10049
10892
  replaceParagraphRunsWithSingleTextRun(paragraph, edit.text);
10050
10893
  }
10894
+ function applyParagraphPropertiesEdit(root, edit) {
10895
+ assertParagraphPropertiesEdit(edit);
10896
+ const locator = parseParagraphLocator(edit.handle.nodeId);
10897
+ const slide = getChild(root, "sld");
10898
+ const cSld = getChild(slide, "cSld");
10899
+ const spTree = getChild(cSld, "spTree");
10900
+ const shape = locateShape(spTree, locator);
10901
+ const paragraphs = getChildArray(getChild(shape, "txBody"), "p");
10902
+ const target = locateParagraphPropertiesForEdit(paragraphs, locator);
10903
+ if (target === void 0) {
10904
+ throw new Error(
10905
+ `writePptx: paragraph properties handle '${edit.handle.nodeId}' no longer matches source XML`
10906
+ );
10907
+ }
10908
+ const set = edit.set ?? {};
10909
+ const hasSet = hasParagraphPropertiesSetValues(set);
10910
+ const existingParagraphProperties = target.properties;
10911
+ if (existingParagraphProperties === void 0 && !hasSet) return;
10912
+ const pPr = existingParagraphProperties ?? ensureParagraphProperties(target.paragraph);
10913
+ let cleared = false;
10914
+ for (const property of edit.clear ?? []) {
10915
+ cleared = clearParagraphProperty(pPr, property) || cleared;
10916
+ }
10917
+ if (set.align !== void 0) pPr["@_algn"] = paragraphAlignOoxmlValue(set.align);
10918
+ if (set.level !== void 0) pPr["@_lvl"] = String(set.level);
10919
+ if (set.bullet !== void 0) setParagraphBullet(pPr, set.bullet);
10920
+ if (!hasSet && cleared && xmlNodeIsEmpty(pPr)) deleteParagraphProperties(target.paragraph, pPr);
10921
+ }
10051
10922
  function locateTextRun(root, nodeId) {
10052
10923
  const locator = parseTextRunLocator(nodeId);
10053
10924
  const slide = getChild(root, "sld");
@@ -10059,7 +10930,7 @@ function locateTextRun(root, nodeId) {
10059
10930
  return getChildArray(paragraph, "r")[locator.runIndex];
10060
10931
  }
10061
10932
  function applyShapeTransformEdit(root, edit) {
10062
- const locator = parseShapeLocator(edit.handle);
10933
+ const locator = parseShapeLocator(edit.handle, "shape transform edit");
10063
10934
  const slide = getChild(root, "sld");
10064
10935
  const cSld = getChild(slide, "cSld");
10065
10936
  const spTree = getChild(cSld, "spTree");
@@ -10082,6 +10953,22 @@ function applyShapeTransformEdit(root, edit) {
10082
10953
  ext["@_cx"] = String(edit.width);
10083
10954
  ext["@_cy"] = String(edit.height);
10084
10955
  }
10956
+ function applyShapeFillEdit(root, edit) {
10957
+ const shape = locateEditableShapeTreeNode(root, edit.handle, "shape fill edit");
10958
+ if (shape.localName === "cxnSp") {
10959
+ throw new Error(
10960
+ `writePptx: shape fill handle '${String(edit.handle.nodeId)}' references a connector`
10961
+ );
10962
+ }
10963
+ const spPr = ensureShapeProperties(shape.node);
10964
+ replaceFillChild(spPr, edit.fill);
10965
+ }
10966
+ function applyShapeOutlineEdit(root, edit) {
10967
+ const shape = locateEditableShapeTreeNode(root, edit.handle, "shape outline edit");
10968
+ const spPr = ensureShapeProperties(shape.node);
10969
+ const ln = ensureLineProperties(spPr);
10970
+ applyOutlinePatch(ln, edit.outline);
10971
+ }
10085
10972
  function applyAddTextBoxEdit(root, edit) {
10086
10973
  const slide = getChild(root, "sld");
10087
10974
  const cSld = getChild(slide, "cSld");
@@ -10104,22 +10991,133 @@ function applyAddConnectorEdit(root, edit) {
10104
10991
  if (locateShapeTreeNode(spTree, { nodeId: edit.shapeId }) !== void 0) {
10105
10992
  throw new Error(`writePptx: shape id '${edit.shapeId}' already exists in source XML`);
10106
10993
  }
10107
- if (locateShapeTreeNode(spTree, { nodeId: edit.startShapeId }) === void 0) {
10994
+ if (edit.startShapeId !== void 0 && locateShapeTreeNode(spTree, { nodeId: edit.startShapeId }) === void 0) {
10108
10995
  throw new Error(`writePptx: connector start shape '${edit.startShapeId}' was not found`);
10109
10996
  }
10110
- if (locateShapeTreeNode(spTree, { nodeId: edit.endShapeId }) === void 0) {
10997
+ if (edit.endShapeId !== void 0 && locateShapeTreeNode(spTree, { nodeId: edit.endShapeId }) === void 0) {
10111
10998
  throw new Error(`writePptx: connector end shape '${edit.endShapeId}' was not found`);
10112
10999
  }
10113
11000
  appendChild(spTree, "p:cxnSp", parseShapeFragmentXml(edit.xml, "cxnSp"));
10114
11001
  }
10115
11002
  function applyDeleteShapeEdit(root, edit) {
10116
- const locator = parseShapeLocator(edit.handle);
11003
+ const locator = parseShapeLocator(edit.handle, "shape delete edit");
10117
11004
  const slide = getChild(root, "sld");
10118
11005
  const cSld = getChild(slide, "cSld");
10119
11006
  const spTree = getChild(cSld, "spTree");
10120
11007
  if (!deleteShapeXml(spTree, locator.nodeId)) {
10121
- throw new Error(`writePptx: shape delete handle '${locator.nodeId}' no longer matches p:sp`);
11008
+ throw new Error(
11009
+ `writePptx: shape delete handle '${locator.nodeId}' no longer matches p:sp or p:cxnSp`
11010
+ );
11011
+ }
11012
+ }
11013
+ function locateEditableShapeTreeNode(root, handle, editName) {
11014
+ const locator = parseShapeLocator(handle, editName);
11015
+ const slide = getChild(root, "sld");
11016
+ const cSld = getChild(slide, "cSld");
11017
+ const spTree = getChild(cSld, "spTree");
11018
+ const shape = locateShapeTreeNodeWithLocalName(spTree, locator.nodeId);
11019
+ if (shape === void 0) {
11020
+ throw new Error(
11021
+ `writePptx: ${editName} handle '${String(handle.nodeId)}' no longer matches source XML`
11022
+ );
11023
+ }
11024
+ if (shape.localName !== "sp" && shape.localName !== "cxnSp") {
11025
+ throw new Error(
11026
+ `writePptx: ${editName} handle '${String(handle.nodeId)}' does not reference p:sp or p:cxnSp`
11027
+ );
11028
+ }
11029
+ return shape;
11030
+ }
11031
+ function locateShapeTreeNodeWithLocalName(spTree, nodeId) {
11032
+ if (spTree === void 0) return void 0;
11033
+ for (const key of Object.keys(spTree)) {
11034
+ if (key.startsWith("@_")) continue;
11035
+ const keyLocalName = localName(key);
11036
+ const value = spTree[key];
11037
+ const items = Array.isArray(value) ? value : [value];
11038
+ for (const item of items) {
11039
+ const node = unsafeOoxmlBoundaryAssertion(item);
11040
+ const nonVisualProperties = getChild(node, "nvSpPr") ?? getChild(node, "nvPicPr") ?? getChild(node, "nvCxnSpPr") ?? getChild(node, "nvGrpSpPr") ?? getChild(node, "nvGraphicFramePr");
11041
+ if (getChild(nonVisualProperties, "cNvPr")?.["@_id"] === nodeId) {
11042
+ return { node, localName: keyLocalName };
11043
+ }
11044
+ }
11045
+ }
11046
+ return void 0;
11047
+ }
11048
+ function ensureShapeProperties(shape) {
11049
+ const existing = getChild(shape, "spPr");
11050
+ if (existing !== void 0) return existing;
11051
+ const entries = [];
11052
+ let inserted = false;
11053
+ for (const [key, value] of Object.entries(shape)) {
11054
+ entries.push([key, value]);
11055
+ if (!inserted && !key.startsWith("@_") && localName(key).startsWith("nv")) {
11056
+ entries.push(["p:spPr", {}]);
11057
+ inserted = true;
11058
+ }
11059
+ }
11060
+ if (!inserted) entries.push(["p:spPr", {}]);
11061
+ replaceNodeEntries(shape, entries);
11062
+ return getChild(shape, "spPr") ?? {};
11063
+ }
11064
+ function ensureLineProperties(spPr) {
11065
+ const existing = getChild(spPr, "ln");
11066
+ if (existing !== void 0) return existing;
11067
+ insertChildByOrder(
11068
+ spPr,
11069
+ "a:ln",
11070
+ {},
11071
+ (name) => ["effectLst", "effectDag", "scene3d", "sp3d", "extLst"].includes(name)
11072
+ );
11073
+ return getChild(spPr, "ln") ?? {};
11074
+ }
11075
+ function applyOutlinePatch(ln, outline) {
11076
+ if (outline.width !== void 0) ln["@_w"] = String(outline.width);
11077
+ if (outline.fill !== void 0) replaceFillChild(ln, outline.fill);
11078
+ }
11079
+ function replaceFillChild(parent, fill) {
11080
+ const fillNode = fill.kind === "none" ? { key: "a:noFill", value: {} } : {
11081
+ key: "a:solidFill",
11082
+ value: { "a:srgbClr": { "@_val": fill.color.hex.toUpperCase() } }
11083
+ };
11084
+ const entries = Object.entries(parent).filter(
11085
+ ([key]) => key.startsWith("@_") || !FILL_CHILD_LOCAL_NAMES.has(localName(key))
11086
+ );
11087
+ replaceNodeEntries(parent, entries);
11088
+ insertChildByOrder(
11089
+ parent,
11090
+ fillNode.key,
11091
+ fillNode.value,
11092
+ (name) => [
11093
+ "ln",
11094
+ "effectLst",
11095
+ "effectDag",
11096
+ "scene3d",
11097
+ "sp3d",
11098
+ "extLst",
11099
+ "prstDash",
11100
+ "custDash",
11101
+ "round",
11102
+ "bevel",
11103
+ "miter",
11104
+ "headEnd",
11105
+ "tailEnd"
11106
+ ].includes(name)
11107
+ );
11108
+ }
11109
+ function insertChildByOrder(node, key, value, shouldInsertBefore) {
11110
+ const entries = [];
11111
+ let inserted = false;
11112
+ for (const [entryKey, entryValue] of Object.entries(node)) {
11113
+ if (!inserted && !entryKey.startsWith("@_") && shouldInsertBefore(localName(entryKey))) {
11114
+ entries.push([key, value]);
11115
+ inserted = true;
11116
+ }
11117
+ entries.push([entryKey, entryValue]);
10122
11118
  }
11119
+ if (!inserted) entries.push([key, value]);
11120
+ replaceNodeEntries(node, entries);
10123
11121
  }
10124
11122
  function parseShapeFragmentXml(xml, rootLocalName) {
10125
11123
  const node = getChild(parseXml(xml), rootLocalName);
@@ -10181,12 +11179,104 @@ function booleanOoxmlValue(value) {
10181
11179
  function hasTextRunPropertiesSetValues(properties) {
10182
11180
  return properties.bold !== void 0 || properties.italic !== void 0 || properties.underline !== void 0 || properties.fontSize !== void 0 || properties.color !== void 0 || properties.typeface !== void 0;
10183
11181
  }
11182
+ function hasParagraphPropertiesSetValues(properties) {
11183
+ return properties.align !== void 0 || properties.level !== void 0 || properties.bullet !== void 0;
11184
+ }
10184
11185
  function assertTextRunPropertiesEdit(edit) {
10185
11186
  const clear = edit.clear ?? [];
10186
11187
  if (!hasTextRunPropertiesSetValues(edit.set ?? {}) && clear.length === 0) {
10187
11188
  throw new Error("writePptx: text run properties edit must set or clear at least one property");
10188
11189
  }
10189
11190
  }
11191
+ function assertParagraphPropertiesEdit(edit) {
11192
+ const clear = edit.clear ?? [];
11193
+ if (!hasParagraphPropertiesSetValues(edit.set ?? {}) && clear.length === 0) {
11194
+ throw new Error("writePptx: paragraph properties edit must set or clear at least one property");
11195
+ }
11196
+ }
11197
+ function locateParagraphPropertiesForEdit(paragraphs, locator) {
11198
+ let logicalParagraphIndex = 0;
11199
+ for (const paragraph of paragraphs) {
11200
+ const logicalCount = getLogicalParagraphCount(paragraph);
11201
+ if (locator.paragraphIndex >= logicalParagraphIndex && locator.paragraphIndex < logicalParagraphIndex + logicalCount) {
11202
+ if (logicalCount === 1) {
11203
+ return { paragraph, properties: getChild(paragraph, "pPr") };
11204
+ }
11205
+ const relativeIndex = locator.paragraphIndex - logicalParagraphIndex;
11206
+ return {
11207
+ paragraph,
11208
+ properties: getBulletParagraphProperties(paragraph)[relativeIndex]
11209
+ };
11210
+ }
11211
+ logicalParagraphIndex += logicalCount;
11212
+ }
11213
+ return void 0;
11214
+ }
11215
+ function getBulletParagraphProperties(paragraph) {
11216
+ return getChildArray(paragraph, "pPr").filter(
11217
+ (properties) => getChild(properties, "buChar") !== void 0 || getChild(properties, "buAutoNum") !== void 0
11218
+ );
11219
+ }
11220
+ function ensureParagraphProperties(paragraph) {
11221
+ const existing = getChild(paragraph, "pPr");
11222
+ if (existing !== void 0) return existing;
11223
+ const entries = [];
11224
+ let inserted = false;
11225
+ for (const [key, value] of Object.entries(paragraph)) {
11226
+ if (!inserted && !key.startsWith("@_")) {
11227
+ entries.push(["a:pPr", {}]);
11228
+ inserted = true;
11229
+ }
11230
+ entries.push([key, value]);
11231
+ }
11232
+ if (!inserted) entries.push(["a:pPr", {}]);
11233
+ replaceNodeEntries(paragraph, entries);
11234
+ return getChild(paragraph, "pPr") ?? {};
11235
+ }
11236
+ function deleteParagraphProperties(paragraph, pPr) {
11237
+ if (getChild(paragraph, "pPr") === pPr) deleteChild(paragraph, "pPr");
11238
+ }
11239
+ function clearParagraphProperty(pPr, property) {
11240
+ switch (property) {
11241
+ case "align":
11242
+ if (pPr["@_algn"] === void 0) return false;
11243
+ delete pPr["@_algn"];
11244
+ return true;
11245
+ case "level":
11246
+ if (pPr["@_lvl"] === void 0) return false;
11247
+ delete pPr["@_lvl"];
11248
+ return true;
11249
+ case "bullet":
11250
+ return deleteParagraphBullet(pPr);
11251
+ }
11252
+ }
11253
+ function deleteParagraphBullet(pPr) {
11254
+ const deletedNone = deleteChild(pPr, "buNone");
11255
+ const deletedChar = deleteChild(pPr, "buChar");
11256
+ const deletedAutoNum = deleteChild(pPr, "buAutoNum");
11257
+ return deletedNone || deletedChar || deletedAutoNum;
11258
+ }
11259
+ function setParagraphBullet(pPr, bullet) {
11260
+ deleteParagraphBullet(pPr);
11261
+ if (bullet.type === "none") {
11262
+ replaceChild(pPr, "buNone", {});
11263
+ return;
11264
+ }
11265
+ if (bullet.type === "char") {
11266
+ replaceChild(pPr, "buChar", { "@_char": bullet.char });
11267
+ return;
11268
+ }
11269
+ replaceChild(pPr, "buAutoNum", {
11270
+ "@_type": bullet.scheme,
11271
+ "@_startAt": String(bullet.startAt)
11272
+ });
11273
+ }
11274
+ function paragraphAlignOoxmlValue(align) {
11275
+ if (align === "center") return "ctr";
11276
+ if (align === "right") return "r";
11277
+ if (align === "justify") return "just";
11278
+ return "l";
11279
+ }
10190
11280
  function replaceParagraphRunsWithSingleTextRun(paragraph, text) {
10191
11281
  const firstRunProperties = getChild(getFirstRunLikeNode(paragraph), "rPr");
10192
11282
  const replacementRun = {
@@ -10255,6 +11345,8 @@ function validateEdits(edits) {
10255
11345
  const runKeys = /* @__PURE__ */ new Set();
10256
11346
  const paragraphKeys = /* @__PURE__ */ new Set();
10257
11347
  const shapeKeys = /* @__PURE__ */ new Set();
11348
+ const shapeFillKeys = /* @__PURE__ */ new Set();
11349
+ const shapeOutlineKeys = /* @__PURE__ */ new Set();
10258
11350
  const deletedShapeKeys = /* @__PURE__ */ new Set();
10259
11351
  const textRunEdits = [];
10260
11352
  const textRunPropertiesEdits = [];
@@ -10283,6 +11375,8 @@ function validateEdits(edits) {
10283
11375
  case "updateTextRunProperties":
10284
11376
  textRunPropertiesEdits.push(edit);
10285
11377
  break;
11378
+ case "updateParagraphProperties":
11379
+ break;
10286
11380
  case "replaceParagraphPlainText": {
10287
11381
  const key = editHandleNodeKey(edit);
10288
11382
  if (paragraphKeys.has(key)) {
@@ -10303,6 +11397,26 @@ function validateEdits(edits) {
10303
11397
  shapeKeys.add(key);
10304
11398
  break;
10305
11399
  }
11400
+ case "updateShapeFill": {
11401
+ const key = editHandleNodeKey(edit);
11402
+ if (shapeFillKeys.has(key)) {
11403
+ throw new Error(
11404
+ `writePptx: conflicting shape fill edits for handle '${String(edit.handle.nodeId)}'`
11405
+ );
11406
+ }
11407
+ shapeFillKeys.add(key);
11408
+ break;
11409
+ }
11410
+ case "updateShapeOutline": {
11411
+ const key = editHandleNodeKey(edit);
11412
+ if (shapeOutlineKeys.has(key)) {
11413
+ throw new Error(
11414
+ `writePptx: conflicting shape outline edits for handle '${String(edit.handle.nodeId)}'`
11415
+ );
11416
+ }
11417
+ shapeOutlineKeys.add(key);
11418
+ break;
11419
+ }
10306
11420
  case "deleteShape": {
10307
11421
  const key = editHandleNodeKey(edit);
10308
11422
  if (deletedShapeKeys.has(key)) {
@@ -10316,6 +11430,7 @@ function validateEdits(edits) {
10316
11430
  case "replaceImage":
10317
11431
  case "addEmptySlideFromLayout":
10318
11432
  case "duplicateSlide":
11433
+ case "moveSlide":
10319
11434
  case "deleteSlide":
10320
11435
  break;
10321
11436
  }
@@ -10422,6 +11537,9 @@ function serializePresentationWithSlideTopologyEdits(source, operations) {
10422
11537
  case "removeSlide":
10423
11538
  removeSlideId(sldIdLst, operation.relationshipId);
10424
11539
  break;
11540
+ case "moveSlide":
11541
+ moveSlideId(sldIdLst, operation.relationshipId, operation.toIndex);
11542
+ break;
10425
11543
  }
10426
11544
  }
10427
11545
  return encodeXml(XML_DECLARATION + xmlBuilder2.build(stripXmlProcessingInstruction(root)));
@@ -10464,6 +11582,24 @@ function removeSlideId(sldIdLst, relationshipId) {
10464
11582
  const { key, items } = slideIdEntries(sldIdLst);
10465
11583
  sldIdLst[key] = items.filter((item) => getRelationshipAttr(item) !== relationshipId);
10466
11584
  }
11585
+ function moveSlideId(sldIdLst, relationshipId, toIndex) {
11586
+ const { key, items } = slideIdEntries(sldIdLst);
11587
+ const fromIndex = items.findIndex((item2) => getRelationshipAttr(item2) === relationshipId);
11588
+ if (fromIndex === -1) {
11589
+ throw new Error(
11590
+ `writePptx: slide relationship '${relationshipId}' was not found in p:sldIdLst`
11591
+ );
11592
+ }
11593
+ if (toIndex < 0 || toIndex >= items.length) {
11594
+ throw new Error(`writePptx: slide move target index '${toIndex}' is out of range`);
11595
+ }
11596
+ if (fromIndex === toIndex) return;
11597
+ const moved = [...items];
11598
+ const [item] = moved.splice(fromIndex, 1);
11599
+ if (item === void 0) return;
11600
+ moved.splice(toIndex, 0, item);
11601
+ sldIdLst[key] = moved;
11602
+ }
10467
11603
  function slideIdEntries(sldIdLst) {
10468
11604
  const key = namespacedChildKey(sldIdLst, "p:sldId", "sldId");
10469
11605
  const value = sldIdLst[key];
@@ -10477,7 +11613,7 @@ function getRelationshipAttr(node) {
10477
11613
  return getNamespacedAttr(node, "id");
10478
11614
  }
10479
11615
  var CONTENT_TYPES_PART2 = "[Content_Types].xml";
10480
- var RELS_CONTENT_TYPE2 = "application/vnd.openxmlformats-package.relationships+xml";
11616
+ var RELS_CONTENT_TYPE3 = "application/vnd.openxmlformats-package.relationships+xml";
10481
11617
  function writePptx(source) {
10482
11618
  const edits = source.edits ?? [];
10483
11619
  validateEdits(edits);
@@ -10524,7 +11660,7 @@ function writePptx(source) {
10524
11660
  }
10525
11661
  for (const part of source.packageGraph.parts) {
10526
11662
  if (written.has(part.partPath)) continue;
10527
- if (part.contentType === RELS_CONTENT_TYPE2 || isRelationshipPart(part.partPath)) continue;
11663
+ if (part.contentType === RELS_CONTENT_TYPE3 || isRelationshipPart(part.partPath)) continue;
10528
11664
  throw new Error(
10529
11665
  "writePptx: no preserved package material for part '" + part.partPath + "'; edited part generation is not implemented in the no-edit writer"
10530
11666
  );
@@ -11411,16 +12547,21 @@ export {
11411
12547
  asSourceNodeId,
11412
12548
  findShapeNodeBySourceHandle,
11413
12549
  updateShapeTransform,
12550
+ setShapeFill,
12551
+ setShapeOutline,
11414
12552
  addTextBox,
11415
12553
  addConnector,
11416
12554
  deleteShape,
11417
12555
  replaceImageBytes,
11418
12556
  addEmptySlideFromLayout,
11419
12557
  duplicateSlide,
12558
+ moveSlide,
11420
12559
  deleteSlide,
11421
12560
  replaceTextRunPlainText,
11422
12561
  setTextRunProperties,
11423
12562
  clearTextRunProperties,
12563
+ setParagraphProperties,
12564
+ clearParagraphProperties,
11424
12565
  replaceParagraphPlainText,
11425
12566
  asEmu2 as asEmu,
11426
12567
  createComputedView,