pptx-glimpse 3.1.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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");
@@ -6353,16 +6828,7 @@ function buildConnectorXml(params) {
6353
6828
  "@_id": params.shapeId,
6354
6829
  "@_name": params.name
6355
6830
  },
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
- },
6831
+ "p:cNvCxnSpPr": createConnectorConnectionXml(params),
6366
6832
  "p:nvPr": {}
6367
6833
  },
6368
6834
  "p:spPr": {
@@ -6385,6 +6851,22 @@ function buildConnectorXml(params) {
6385
6851
  }
6386
6852
  });
6387
6853
  }
6854
+ function createConnectorConnectionXml(params) {
6855
+ return {
6856
+ ...params.startShapeId !== void 0 && params.startConnectionSiteIndex !== void 0 ? {
6857
+ "a:stCxn": {
6858
+ "@_id": params.startShapeId,
6859
+ "@_idx": String(params.startConnectionSiteIndex)
6860
+ }
6861
+ } : {},
6862
+ ...params.endShapeId !== void 0 && params.endConnectionSiteIndex !== void 0 ? {
6863
+ "a:endCxn": {
6864
+ "@_id": params.endShapeId,
6865
+ "@_idx": String(params.endConnectionSiteIndex)
6866
+ }
6867
+ } : {}
6868
+ };
6869
+ }
6388
6870
  function createConnectorLineXml(params) {
6389
6871
  return {
6390
6872
  "a:solidFill": {
@@ -6424,8 +6906,8 @@ var CONNECTOR_PRESETS = /* @__PURE__ */ new Set([
6424
6906
  "bentConnector3",
6425
6907
  "curvedConnector3"
6426
6908
  ]);
6427
- var ARROW_TYPES = /* @__PURE__ */ new Set(["triangle", "stealth", "diamond", "oval", "arrow"]);
6428
- var ARROW_SIZES = /* @__PURE__ */ new Set(["sm", "med", "lg"]);
6909
+ var ARROW_TYPES2 = /* @__PURE__ */ new Set(["triangle", "stealth", "diamond", "oval", "arrow"]);
6910
+ var ARROW_SIZES2 = /* @__PURE__ */ new Set(["sm", "med", "lg"]);
6429
6911
  function findShapeNodeBySourceHandle(source, handle) {
6430
6912
  for (const slide of source.slides) {
6431
6913
  const shape = findShapeNodeInTree(slide.shapes, handle);
@@ -6468,25 +6950,111 @@ function updateShapeTransform(source, handle, transform) {
6468
6950
  });
6469
6951
  if (!matched) {
6470
6952
  if (source.slides.some((slide) => hasNestedShapeNodeWithHandle(slide.shapes, handle))) {
6471
- throw new Error("updateShapeTransform: nested group shape editing is not supported");
6953
+ throw new Error("updateShapeTransform: nested group shape editing is not supported");
6954
+ }
6955
+ throw new Error("updateShapeTransform: shape handle was not found in PptxSourceModel source");
6956
+ }
6957
+ if (!changed) return source;
6958
+ return {
6959
+ ...source,
6960
+ slides,
6961
+ edits: [
6962
+ ...source.edits ?? [],
6963
+ {
6964
+ kind: "updateShapeTransform",
6965
+ handle,
6966
+ offsetX: transform.offsetX,
6967
+ offsetY: transform.offsetY,
6968
+ width: transform.width,
6969
+ height: transform.height
6970
+ }
6971
+ ]
6972
+ };
6973
+ }
6974
+ function setShapeFill(source, handle, fill) {
6975
+ assertEditableShapeFill(fill, "setShapeFill");
6976
+ if (handle.nodeId === void 0) {
6977
+ throw new Error("setShapeFill: shape fill edit requires a node id");
6978
+ }
6979
+ let matched = false;
6980
+ let changed = false;
6981
+ const slides = source.slides.map((slide) => {
6982
+ let slideChanged = false;
6983
+ const shapes = slide.shapes.map((shape) => {
6984
+ if (!sourceHandlesEqual(shape.handle, handle)) return shape;
6985
+ matched = true;
6986
+ if (shape.kind !== "shape") {
6987
+ throw new Error("setShapeFill: only top-level sp shapes support fill edits");
6988
+ }
6989
+ if (hasAlternateContentSidecar(shape)) {
6990
+ throw new Error("setShapeFill: shapes inside AlternateContent are not supported");
6991
+ }
6992
+ const nextFill = toSourceFill(fill);
6993
+ if (sourceFillEqual(shape.fill, nextFill)) return shape;
6994
+ changed = true;
6995
+ slideChanged = true;
6996
+ return {
6997
+ ...shape,
6998
+ fill: nextFill
6999
+ };
7000
+ });
7001
+ return slideChanged ? { ...slide, shapes } : slide;
7002
+ });
7003
+ if (!matched) {
7004
+ if (source.slides.some((slide) => hasNestedShapeNodeWithHandle(slide.shapes, handle))) {
7005
+ throw new Error("setShapeFill: nested group shape editing is not supported");
7006
+ }
7007
+ throw new Error("setShapeFill: shape handle was not found in PptxSourceModel source");
7008
+ }
7009
+ if (!changed) return source;
7010
+ return {
7011
+ ...source,
7012
+ slides,
7013
+ edits: appendShapeFillEdit(source.edits ?? [], handle, fill)
7014
+ };
7015
+ }
7016
+ function setShapeOutline(source, handle, outline) {
7017
+ assertEditableShapeOutline(outline, "setShapeOutline");
7018
+ if (handle.nodeId === void 0) {
7019
+ throw new Error("setShapeOutline: shape outline edit requires a node id");
7020
+ }
7021
+ let matched = false;
7022
+ let changed = false;
7023
+ const slides = source.slides.map((slide) => {
7024
+ let slideChanged = false;
7025
+ const shapes = slide.shapes.map((shape) => {
7026
+ if (!sourceHandlesEqual(shape.handle, handle)) return shape;
7027
+ matched = true;
7028
+ if (shape.kind !== "shape" && shape.kind !== "connector") {
7029
+ throw new Error(
7030
+ "setShapeOutline: only top-level sp and cxnSp shapes support outline edits"
7031
+ );
7032
+ }
7033
+ if (hasAlternateContentSidecar(shape)) {
7034
+ throw new Error("setShapeOutline: shapes inside AlternateContent are not supported");
7035
+ }
7036
+ const nextOutline = patchSourceOutline(shape.outline, outline);
7037
+ if (sourceOutlineEqual(shape.outline, nextOutline)) return shape;
7038
+ changed = true;
7039
+ slideChanged = true;
7040
+ return {
7041
+ ...shape,
7042
+ outline: nextOutline
7043
+ };
7044
+ });
7045
+ return slideChanged ? { ...slide, shapes } : slide;
7046
+ });
7047
+ if (!matched) {
7048
+ if (source.slides.some((slide) => hasNestedShapeNodeWithHandle(slide.shapes, handle))) {
7049
+ throw new Error("setShapeOutline: nested group shape editing is not supported");
6472
7050
  }
6473
- throw new Error("updateShapeTransform: shape handle was not found in PptxSourceModel source");
7051
+ throw new Error("setShapeOutline: shape handle was not found in PptxSourceModel source");
6474
7052
  }
6475
7053
  if (!changed) return source;
6476
7054
  return {
6477
7055
  ...source,
6478
7056
  slides,
6479
- edits: [
6480
- ...source.edits ?? [],
6481
- {
6482
- kind: "updateShapeTransform",
6483
- handle,
6484
- offsetX: transform.offsetX,
6485
- offsetY: transform.offsetY,
6486
- width: transform.width,
6487
- height: transform.height
6488
- }
6489
- ]
7057
+ edits: appendShapeOutlineEdit(source.edits ?? [], handle, outline)
6490
7058
  };
6491
7059
  }
6492
7060
  function addTextBox(source, slideHandle, input) {
@@ -6541,14 +7109,14 @@ function addConnector(source, slideHandle, input) {
6541
7109
  throw new Error("addConnector: slide handle was not found in PptxSourceModel source");
6542
7110
  }
6543
7111
  const slide = source.slides[slideIndex];
6544
- const startShape = requireConnectorTargetShape(slide, input.start.shapeHandle, "start");
6545
- const endShape = requireConnectorTargetShape(slide, input.end.shapeHandle, "end");
7112
+ const startShape = input.start !== void 0 ? requireConnectorTargetShape(slide, input.start.shapeHandle, "start") : void 0;
7113
+ const endShape = input.end !== void 0 ? requireConnectorTargetShape(slide, input.end.shapeHandle, "end") : void 0;
6546
7114
  const shapeId = nextShapeId(slide.shapes, source.edits ?? [], slide.partPath);
6547
7115
  const shapeIdValue = String(shapeId);
6548
7116
  const name = input.name?.trim() || `Connector ${shapeIdValue}`;
6549
7117
  const orderingSlot = nextOrderingSlot(slide.shapes);
6550
- const startShapeId = String(startShape.nodeId);
6551
- const endShapeId = String(endShape.nodeId);
7118
+ const startShapeId = startShape !== void 0 ? String(startShape.nodeId) : void 0;
7119
+ const endShapeId = endShape !== void 0 ? String(endShape.nodeId) : void 0;
6552
7120
  const xml = buildConnectorXml({
6553
7121
  shapeId: shapeIdValue,
6554
7122
  name,
@@ -6557,10 +7125,14 @@ function addConnector(source, slideHandle, input) {
6557
7125
  offsetY: input.offsetY,
6558
7126
  width: input.width,
6559
7127
  height: input.height,
6560
- startShapeId,
6561
- startConnectionSiteIndex: input.start.connectionSiteIndex,
6562
- endShapeId,
6563
- endConnectionSiteIndex: input.end.connectionSiteIndex,
7128
+ ...startShapeId !== void 0 && input.start !== void 0 ? {
7129
+ startShapeId,
7130
+ startConnectionSiteIndex: input.start.connectionSiteIndex
7131
+ } : {},
7132
+ ...endShapeId !== void 0 && input.end !== void 0 ? {
7133
+ endShapeId,
7134
+ endConnectionSiteIndex: input.end.connectionSiteIndex
7135
+ } : {},
6564
7136
  ...input.outline !== void 0 ? { outline: input.outline } : {}
6565
7137
  });
6566
7138
  const connector = parseShapeNodeXml(xml, slide.partPath, orderingSlot);
@@ -6579,8 +7151,8 @@ function addConnector(source, slideHandle, input) {
6579
7151
  kind: "addConnector",
6580
7152
  slidePartPath: slide.partPath,
6581
7153
  shapeId: shapeIdValue,
6582
- startShapeId,
6583
- endShapeId,
7154
+ ...startShapeId !== void 0 ? { startShapeId } : {},
7155
+ ...endShapeId !== void 0 ? { endShapeId } : {},
6584
7156
  xml
6585
7157
  }
6586
7158
  ]
@@ -6597,8 +7169,8 @@ function deleteShape(source, handle) {
6597
7169
  const nextShapes = slide.shapes.filter((shape) => {
6598
7170
  if (!sourceHandlesEqual(shape.handle, handle)) return true;
6599
7171
  found = shape;
6600
- if (shape.kind !== "shape") {
6601
- throw new Error("deleteShape: only top-level sp shapes can be deleted");
7172
+ if (shape.kind !== "shape" && shape.kind !== "connector") {
7173
+ throw new Error("deleteShape: only top-level sp or cxnSp shapes can be deleted");
6602
7174
  }
6603
7175
  if (hasAlternateContentSidecar(shape)) {
6604
7176
  throw new Error("deleteShape: shapes inside AlternateContent are not supported");
@@ -6641,6 +7213,99 @@ function deleteShape(source, handle) {
6641
7213
  function shapeTransformPositionAndSizeEqual(current, next) {
6642
7214
  return current?.offsetX === next.offsetX && current.offsetY === next.offsetY && current.width === next.width && current.height === next.height;
6643
7215
  }
7216
+ function patchSourceOutline(current, patch) {
7217
+ return {
7218
+ ...current ?? {},
7219
+ ...patch.width !== void 0 ? { width: patch.width } : {},
7220
+ ...patch.fill !== void 0 ? { fill: toSourceFill(patch.fill) } : {}
7221
+ };
7222
+ }
7223
+ function appendShapeFillEdit(edits, handle, fill) {
7224
+ const retainedEdits = edits.filter(
7225
+ (edit) => edit.kind !== "updateShapeFill" || !sourceHandlesEqual(edit.handle, handle)
7226
+ );
7227
+ return [...retainedEdits, { kind: "updateShapeFill", handle, fill }];
7228
+ }
7229
+ function appendShapeOutlineEdit(edits, handle, outline) {
7230
+ let outlineEdit = {
7231
+ kind: "updateShapeOutline",
7232
+ handle,
7233
+ outline
7234
+ };
7235
+ const retainedEdits = [];
7236
+ for (const edit of edits) {
7237
+ if (edit.kind !== "updateShapeOutline" || !sourceHandlesEqual(edit.handle, handle)) {
7238
+ retainedEdits.push(edit);
7239
+ continue;
7240
+ }
7241
+ outlineEdit = {
7242
+ ...outlineEdit,
7243
+ outline: mergeEditableShapeOutline(edit.outline, outlineEdit.outline)
7244
+ };
7245
+ }
7246
+ return [...retainedEdits, outlineEdit];
7247
+ }
7248
+ function mergeEditableShapeOutline(base, patch) {
7249
+ return {
7250
+ ...base.width !== void 0 ? { width: base.width } : {},
7251
+ ...base.fill !== void 0 ? { fill: base.fill } : {},
7252
+ ...patch.width !== void 0 ? { width: patch.width } : {},
7253
+ ...patch.fill !== void 0 ? { fill: patch.fill } : {}
7254
+ };
7255
+ }
7256
+ function toSourceFill(fill) {
7257
+ if (fill.kind === "none") return { kind: "none" };
7258
+ return {
7259
+ kind: "solid",
7260
+ color: { kind: "srgb", hex: fill.color.hex }
7261
+ };
7262
+ }
7263
+ function assertEditableShapeFill(fill, operationName) {
7264
+ if (fill.kind === "none") return;
7265
+ if (fill.kind !== "solid") {
7266
+ throw new Error(`${operationName}: only solid and none fills are supported`);
7267
+ }
7268
+ if (fill.color.kind !== "srgb") {
7269
+ throw new Error(`${operationName}: only srgb solid fill colors are supported`);
7270
+ }
7271
+ if (!/^[0-9A-Fa-f]{6}$/.test(fill.color.hex)) {
7272
+ throw new Error(`${operationName}: srgb fill color must be a 6-digit hex value`);
7273
+ }
7274
+ }
7275
+ function assertEditableShapeOutline(outline, operationName) {
7276
+ if (outline.width === void 0 && outline.fill === void 0) {
7277
+ throw new Error(`${operationName}: outline must set width or fill`);
7278
+ }
7279
+ if (outline.width !== void 0) {
7280
+ assertPositiveFiniteEmu(outline.width, operationName, "width");
7281
+ }
7282
+ if (outline.fill !== void 0) assertEditableShapeFill(outline.fill, operationName);
7283
+ }
7284
+ function sourceFillEqual(left, right) {
7285
+ return stableValueEqual(left ?? {}, right ?? {});
7286
+ }
7287
+ function sourceOutlineEqual(left, right) {
7288
+ return stableValueEqual(left ?? {}, right ?? {});
7289
+ }
7290
+ function stableValueEqual(left, right) {
7291
+ if (Object.is(left, right)) return true;
7292
+ if (Array.isArray(left) || Array.isArray(right)) {
7293
+ if (!Array.isArray(left) || !Array.isArray(right)) return false;
7294
+ if (left.length !== right.length) return false;
7295
+ return left.every((value, index) => stableValueEqual(value, right[index]));
7296
+ }
7297
+ if (isPlainRecord(left) || isPlainRecord(right)) {
7298
+ if (!isPlainRecord(left) || !isPlainRecord(right)) return false;
7299
+ const leftKeys = Object.keys(left).sort();
7300
+ const rightKeys = Object.keys(right).sort();
7301
+ if (!stableValueEqual(leftKeys, rightKeys)) return false;
7302
+ return leftKeys.every((key) => stableValueEqual(left[key], right[key]));
7303
+ }
7304
+ return false;
7305
+ }
7306
+ function isPlainRecord(value) {
7307
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7308
+ }
6644
7309
  function hasEditableTransform(shape) {
6645
7310
  return shape.kind !== "raw" && shape.transform !== void 0;
6646
7311
  }
@@ -6666,8 +7331,9 @@ function assertConnectorInput(input) {
6666
7331
  "addConnector: preset must be straightConnector1, bentConnector3, or curvedConnector3"
6667
7332
  );
6668
7333
  }
6669
- assertConnectionSiteIndex(input.start.connectionSiteIndex, "start");
6670
- assertConnectionSiteIndex(input.end.connectionSiteIndex, "end");
7334
+ if (input.start !== void 0)
7335
+ assertConnectionSiteIndex(input.start.connectionSiteIndex, "start");
7336
+ if (input.end !== void 0) assertConnectionSiteIndex(input.end.connectionSiteIndex, "end");
6671
7337
  if (input.name !== void 0 && input.name.trim() === "") {
6672
7338
  throw new Error("addConnector: name must be a non-empty string when provided");
6673
7339
  }
@@ -6683,13 +7349,13 @@ function assertConnectionSiteIndex(value, fieldName) {
6683
7349
  }
6684
7350
  function assertArrowEndpoint(endpoint, fieldName) {
6685
7351
  if (endpoint === void 0) return;
6686
- if (!ARROW_TYPES.has(endpoint.type)) {
7352
+ if (!ARROW_TYPES2.has(endpoint.type)) {
6687
7353
  throw new Error(`addConnector: outline.${fieldName}.type is not supported`);
6688
7354
  }
6689
- if (!ARROW_SIZES.has(endpoint.width)) {
7355
+ if (!ARROW_SIZES2.has(endpoint.width)) {
6690
7356
  throw new Error(`addConnector: outline.${fieldName}.width is not supported`);
6691
7357
  }
6692
- if (!ARROW_SIZES.has(endpoint.length)) {
7358
+ if (!ARROW_SIZES2.has(endpoint.length)) {
6693
7359
  throw new Error(`addConnector: outline.${fieldName}.length is not supported`);
6694
7360
  }
6695
7361
  }
@@ -7084,6 +7750,45 @@ function duplicateSlide(source, slideHandle) {
7084
7750
  ]
7085
7751
  };
7086
7752
  }
7753
+ function moveSlide(source, slideHandle, input) {
7754
+ assertValidSlideIndex(input.toIndex, source.slides.length, "moveSlide");
7755
+ const slideIndex = source.slides.findIndex(
7756
+ (slide2) => sourceHandlesEqual(slide2.handle, slideHandle)
7757
+ );
7758
+ if (slideIndex === -1) {
7759
+ throw new Error("moveSlide: slide handle was not found in PptxSourceModel source");
7760
+ }
7761
+ if (slideIndex === input.toIndex) return source;
7762
+ const slide = source.slides[slideIndex];
7763
+ const presentationRels = requirePartRelationships(
7764
+ source,
7765
+ source.presentation.partPath,
7766
+ "moveSlide"
7767
+ );
7768
+ const presentationRelationship = requireSlideRelationship(
7769
+ source,
7770
+ presentationRels,
7771
+ slide.partPath,
7772
+ "moveSlide"
7773
+ );
7774
+ return {
7775
+ ...source,
7776
+ presentation: {
7777
+ ...source.presentation,
7778
+ slidePartPaths: moveReadonly(source.presentation.slidePartPaths, slideIndex, input.toIndex)
7779
+ },
7780
+ slides: moveReadonly(source.slides, slideIndex, input.toIndex),
7781
+ edits: [
7782
+ ...source.edits ?? [],
7783
+ {
7784
+ kind: "moveSlide",
7785
+ slidePartPath: slide.partPath,
7786
+ relationshipId: presentationRelationship.id,
7787
+ toIndex: input.toIndex
7788
+ }
7789
+ ]
7790
+ };
7791
+ }
7087
7792
  function deleteSlide(source, slideHandle) {
7088
7793
  if (source.slides.length <= 1) {
7089
7794
  throw new Error("deleteSlide: cannot delete the last slide");
@@ -7166,766 +7871,500 @@ function createNotesSlideCopy(source, sourceSlide, slideRelationships, newSlideP
7166
7871
  (relationships) => relationships.sourcePartPath === notesPartPath
7167
7872
  );
7168
7873
  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 } : {}
7874
+ slideRelationshipId: notesRelationship.id,
7875
+ newPartPath,
7876
+ contentType,
7877
+ raw,
7878
+ ...notesRelationships === void 0 ? {} : {
7879
+ relationships: {
7880
+ sourcePartPath: newPartPath,
7881
+ relationships: notesRelationships.relationships.map(
7882
+ (relationship) => relationship.type === SLIDE_REL_TYPE && relationship.targetMode !== "External" ? { ...relationship, target: relativeTarget(newPartPath, newSlidePartPath) } : relationship
7883
+ )
7338
7884
  }
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
7885
  }
7365
- return { paragraph: mapParagraph(paragraph), matched: true };
7366
- });
7886
+ };
7367
7887
  }
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
- });
7888
+ function withPartPath(slide, partPath) {
7396
7889
  return {
7397
- slides: changed ? slides : source.slides,
7398
- matched,
7399
- changed
7890
+ ...slide,
7891
+ partPath,
7892
+ handle: { partPath },
7893
+ shapes: slide.shapes.map((shape) => withShapePartPath(shape, partPath))
7400
7894
  };
7401
7895
  }
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]));
7896
+ function withShapePartPath(shape, partPath) {
7897
+ if (shape.kind === "raw") return shape;
7898
+ const handle = shape.handle === void 0 ? void 0 : { ...shape.handle, partPath };
7899
+ if (shape.kind === "group") {
7900
+ return {
7901
+ ...shape,
7902
+ ...handle !== void 0 ? { handle } : {},
7903
+ children: shape.children.map((child) => withShapePartPath(child, partPath))
7904
+ };
7461
7905
  }
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]));
7906
+ if (shape.kind !== "shape" || shape.textBody === void 0) {
7907
+ return { ...shape, ...handle !== void 0 ? { handle } : {} };
7468
7908
  }
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
7909
  return {
7478
- ...paragraph.handle,
7479
- nodeId: asSourceNodeId(`${paragraph.handle.nodeId}:r:0`),
7480
- orderingSlot: 0
7910
+ ...shape,
7911
+ ...handle !== void 0 ? { handle } : {},
7912
+ textBody: {
7913
+ ...shape.textBody,
7914
+ paragraphs: shape.textBody.paragraphs.map((paragraph) => ({
7915
+ ...paragraph,
7916
+ ...paragraph.handle !== void 0 ? { handle: { ...paragraph.handle, partPath } } : {},
7917
+ runs: paragraph.runs.map((run) => ({
7918
+ ...run,
7919
+ ...run.handle !== void 0 ? { handle: { ...run.handle, partPath } } : {}
7920
+ }))
7921
+ }))
7922
+ }
7481
7923
  };
7482
7924
  }
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);
7925
+ function assertValidSlideIndex(index, slideCount, operationName) {
7926
+ if (!Number.isInteger(index) || index < 0 || index >= slideCount) {
7927
+ throw new Error(`${operationName}: toIndex must be an integer slide index in range`);
7928
+ }
7494
7929
  }
7495
- function asOoxmlAngle(value) {
7496
- return unsafeBrandAssertion2(value);
7930
+ function moveReadonly(items, fromIndex, toIndex) {
7931
+ const moved = [...items];
7932
+ const [item] = moved.splice(fromIndex, 1);
7933
+ if (item === void 0) return items;
7934
+ moved.splice(toIndex, 0, item);
7935
+ return moved;
7497
7936
  }
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);
7937
+ var EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS = {
7938
+ bold: (value) => requireBooleanOrUndefined(value, "bold"),
7939
+ italic: (value) => requireBooleanOrUndefined(value, "italic"),
7940
+ underline: (value) => requireBooleanOrUndefined(value, "underline"),
7941
+ fontSize: (value) => {
7942
+ if (value !== void 0 && (!Number.isFinite(value) || value <= 0)) {
7943
+ throw new Error("updateTextRunProperties: fontSize must be a finite positive pt value");
7534
7944
  }
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);
7945
+ },
7946
+ color: (value) => {
7947
+ if (value === void 0) return;
7948
+ if (value.kind !== "srgb") {
7949
+ throw new Error("updateTextRunProperties: only srgb text run color is supported");
7950
+ }
7951
+ if (!/^[0-9A-Fa-f]{6}$/.test(value.hex)) {
7952
+ throw new Error("updateTextRunProperties: srgb text run color must be a 6-digit hex value");
7953
+ }
7954
+ },
7955
+ typeface: (value) => {
7956
+ if (value !== void 0 && value.trim() === "") {
7957
+ throw new Error("updateTextRunProperties: typeface must be a non-empty string");
7541
7958
  }
7542
7959
  }
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
- }
7960
+ };
7961
+ var EDITABLE_TEXT_RUN_PROPERTIES = Object.keys(EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS).filter(
7962
+ (property) => property in EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS
7963
+ );
7964
+ var EDITABLE_TEXT_RUN_PROPERTY_SET = new Set(EDITABLE_TEXT_RUN_PROPERTIES);
7965
+ var EDITABLE_PARAGRAPH_PROPERTIES = [
7966
+ "align",
7967
+ "level",
7968
+ "bullet"
7969
+ ];
7970
+ var EDITABLE_PARAGRAPH_PROPERTY_SET = new Set(EDITABLE_PARAGRAPH_PROPERTIES);
7971
+ var TEXT_ALIGN_VALUES = /* @__PURE__ */ new Set([
7972
+ "left",
7973
+ "center",
7974
+ "right",
7975
+ "justify"
7976
+ ]);
7977
+ var AUTO_NUM_SCHEMES = /* @__PURE__ */ new Set([
7978
+ "arabicPeriod",
7979
+ "arabicParenR",
7980
+ "romanUcPeriod",
7981
+ "romanLcPeriod",
7982
+ "alphaUcPeriod",
7983
+ "alphaLcPeriod",
7984
+ "alphaLcParenR",
7985
+ "alphaUcParenR",
7986
+ "arabicPlain"
7987
+ ]);
7988
+ function replaceTextRunPlainText(source, handle, text) {
7989
+ const result = mapMatchingTextRun(
7990
+ source,
7991
+ handle,
7992
+ (run) => run.text === text ? run : { ...run, text }
7993
+ );
7994
+ if (!result.matched) {
7995
+ throw new Error(
7996
+ "replaceTextRunPlainText: text run handle was not found in PptxSourceModel source"
7997
+ );
7557
7998
  }
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 } : {}
7999
+ if (!result.changed) return source;
8000
+ return {
8001
+ ...source,
8002
+ slides: result.slides,
8003
+ edits: [...source.edits ?? [], { kind: "replaceTextRunPlainText", handle, text }]
7571
8004
  };
7572
- return Object.keys(parsed).length > 0 ? parsed : void 0;
7573
8005
  }
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;
8006
+ function setTextRunProperties(source, handle, properties) {
8007
+ return updateTextRunProperties(source, handle, {
8008
+ set: properties,
8009
+ clear: []
8010
+ });
7591
8011
  }
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
- };
8012
+ function clearTextRunProperties(source, handle, properties) {
8013
+ return updateTextRunProperties(source, handle, {
8014
+ set: {},
8015
+ clear: properties
8016
+ });
7604
8017
  }
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
- };
8018
+ function setParagraphProperties(source, handle, properties) {
8019
+ return updateParagraphProperties(source, handle, {
8020
+ set: properties,
8021
+ clear: []
8022
+ });
7615
8023
  }
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
- };
8024
+ function clearParagraphProperties(source, handle, properties) {
8025
+ return updateParagraphProperties(source, handle, {
8026
+ set: {},
8027
+ clear: properties
8028
+ });
7624
8029
  }
7625
- function parseSoftEdge(node) {
7626
- if (node === void 0) return void 0;
8030
+ function replaceParagraphPlainText(source, handle, text) {
8031
+ const result = mapMatchingParagraph(source, handle, (paragraph) => {
8032
+ const replacementHandle = createReplacementRunHandle(paragraph);
8033
+ return {
8034
+ ...paragraph,
8035
+ runs: [
8036
+ {
8037
+ kind: "textRun",
8038
+ text,
8039
+ ...paragraph.runs[0]?.properties !== void 0 ? { properties: paragraph.runs[0].properties } : {},
8040
+ ...replacementHandle !== void 0 ? { handle: replacementHandle } : {}
8041
+ }
8042
+ ]
8043
+ };
8044
+ });
8045
+ if (!result.matched) {
8046
+ throw new Error(
8047
+ "replaceParagraphPlainText: paragraph handle was not found in PptxSourceModel source"
8048
+ );
8049
+ }
7627
8050
  return {
7628
- radius: asEmu2(numericAttr2(node, "rad") ?? 0)
8051
+ ...source,
8052
+ slides: result.slides,
8053
+ edits: [...source.edits ?? [], { kind: "replaceParagraphPlainText", handle, text }]
7629
8054
  };
7630
8055
  }
7631
- function parseBiLevel(node) {
7632
- if (node === void 0) return void 0;
8056
+ function updateTextRunProperties(source, handle, patch) {
8057
+ assertEditableTextRunProperties(patch.set);
8058
+ assertEditableTextRunPropertyNames(patch.clear);
8059
+ const set = definedEditableTextRunProperties(patch.set);
8060
+ if (Object.values(set).every((value) => value === void 0) && patch.clear.length === 0) {
8061
+ throw new Error("updateTextRunProperties: patch must set or clear at least one property");
8062
+ }
8063
+ const result = mapMatchingTextRun(source, handle, (run) => {
8064
+ const properties = patchTextRunProperties(run.properties, { set, clear: patch.clear });
8065
+ if (textRunPropertiesEqual(run.properties, properties)) return run;
8066
+ return {
8067
+ kind: run.kind,
8068
+ text: run.text,
8069
+ ...run.handle !== void 0 ? { handle: run.handle } : {},
8070
+ ...run.rawSidecars !== void 0 ? { rawSidecars: run.rawSidecars } : {},
8071
+ ...properties !== void 0 ? { properties } : {}
8072
+ };
8073
+ });
8074
+ if (!result.matched) {
8075
+ throw new Error(
8076
+ "updateTextRunProperties: text run handle was not found in PptxSourceModel source"
8077
+ );
8078
+ }
8079
+ if (!result.changed) return source;
7633
8080
  return {
7634
- threshold: (numericAttr2(node, "thresh") ?? 5e4) / 1e5
8081
+ ...source,
8082
+ slides: result.slides,
8083
+ edits: [
8084
+ ...source.edits ?? [],
8085
+ {
8086
+ kind: "updateTextRunProperties",
8087
+ handle,
8088
+ ...Object.keys(set).length > 0 ? { set } : {},
8089
+ ...patch.clear.length > 0 ? { clear: patch.clear } : {}
8090
+ }
8091
+ ]
7635
8092
  };
7636
8093
  }
7637
- function parseBlurEffect(node) {
7638
- if (node === void 0) return void 0;
8094
+ function updateParagraphProperties(source, handle, patch) {
8095
+ assertEditableParagraphProperties(patch.set);
8096
+ assertEditableParagraphPropertyNames(patch.clear);
8097
+ const set = definedEditableParagraphProperties(patch.set);
8098
+ if (Object.values(set).every((value) => value === void 0) && patch.clear.length === 0) {
8099
+ throw new Error("updateParagraphProperties: patch must set or clear at least one property");
8100
+ }
8101
+ const result = mapMatchingParagraph(source, handle, (paragraph) => {
8102
+ const properties = patchParagraphProperties(paragraph.properties, { set, clear: patch.clear });
8103
+ if (paragraphPropertiesEqual(paragraph.properties, properties)) return paragraph;
8104
+ return {
8105
+ runs: paragraph.runs,
8106
+ ...paragraph.handle !== void 0 ? { handle: paragraph.handle } : {},
8107
+ ...paragraph.rawSidecars !== void 0 ? { rawSidecars: paragraph.rawSidecars } : {},
8108
+ ...properties !== void 0 ? { properties } : {}
8109
+ };
8110
+ });
8111
+ if (!result.matched) {
8112
+ throw new Error(
8113
+ "updateParagraphProperties: paragraph handle was not found in PptxSourceModel source"
8114
+ );
8115
+ }
8116
+ if (!result.changed) return source;
7639
8117
  return {
7640
- radius: asEmu2(numericAttr2(node, "rad") ?? 0),
7641
- grow: getAttr(node, "grow") !== "0"
8118
+ ...source,
8119
+ slides: result.slides,
8120
+ edits: [
8121
+ ...source.edits ?? [],
8122
+ {
8123
+ kind: "updateParagraphProperties",
8124
+ handle,
8125
+ ...Object.keys(set).length > 0 ? { set } : {},
8126
+ ...patch.clear.length > 0 ? { clear: patch.clear } : {}
8127
+ }
8128
+ ]
7642
8129
  };
7643
8130
  }
7644
- function parseLumEffect(node) {
7645
- if (node === void 0) return void 0;
8131
+ function mapMatchingTextRun(source, handle, mapRun) {
8132
+ return mapTextBodyParagraphs(source, (paragraph) => {
8133
+ let matched = false;
8134
+ let changed = false;
8135
+ const runs = paragraph.runs.map((run) => {
8136
+ if (!sourceHandlesEqual(run.handle, handle)) return run;
8137
+ matched = true;
8138
+ const mapped = mapRun(run);
8139
+ if (mapped === run) return run;
8140
+ changed = true;
8141
+ return mapped;
8142
+ });
8143
+ return {
8144
+ paragraph: changed ? { ...paragraph, runs } : paragraph,
8145
+ matched
8146
+ };
8147
+ });
8148
+ }
8149
+ function mapMatchingParagraph(source, handle, mapParagraph) {
8150
+ return mapTextBodyParagraphs(source, (paragraph) => {
8151
+ if (!sourceHandlesEqual(paragraph.handle, handle)) {
8152
+ return { paragraph, matched: false };
8153
+ }
8154
+ return { paragraph: mapParagraph(paragraph), matched: true };
8155
+ });
8156
+ }
8157
+ function mapTextBodyParagraphs(source, mapParagraph) {
8158
+ let matched = false;
8159
+ let changed = false;
8160
+ const slides = source.slides.map((slide) => {
8161
+ let slideChanged = false;
8162
+ const shapes = slide.shapes.map((shape) => {
8163
+ if (shape.kind !== "shape" || shape.textBody === void 0) return shape;
8164
+ let shapeChanged = false;
8165
+ const paragraphs = shape.textBody.paragraphs.map((paragraph) => {
8166
+ const result = mapParagraph(paragraph);
8167
+ if (result.matched) matched = true;
8168
+ if (result.paragraph === paragraph) return paragraph;
8169
+ changed = true;
8170
+ shapeChanged = true;
8171
+ slideChanged = true;
8172
+ return result.paragraph;
8173
+ });
8174
+ if (!shapeChanged) return shape;
8175
+ return {
8176
+ ...shape,
8177
+ textBody: {
8178
+ ...shape.textBody,
8179
+ paragraphs
8180
+ }
8181
+ };
8182
+ });
8183
+ return slideChanged ? { ...slide, shapes } : slide;
8184
+ });
7646
8185
  return {
7647
- brightness: (numericAttr2(node, "bright") ?? 0) / 1e5,
7648
- contrast: (numericAttr2(node, "contrast") ?? 0) / 1e5
8186
+ slides: changed ? slides : source.slides,
8187
+ matched,
8188
+ changed
7649
8189
  };
7650
8190
  }
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
- }
8191
+ function patchTextRunProperties(current, patch) {
8192
+ const next = { ...current ?? {} };
8193
+ for (const property of patch.clear) {
8194
+ delete next[property];
7673
8195
  }
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;
8196
+ Object.assign(next, patch.set);
8197
+ return Object.keys(next).length > 0 ? next : void 0;
7690
8198
  }
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) };
8199
+ function patchParagraphProperties(current, patch) {
8200
+ const next = { ...current ?? {} };
8201
+ for (const property of patch.clear) {
8202
+ delete next[property];
7704
8203
  }
7705
- const blip = getChild(parent, "blipFill");
7706
- if (blip) {
7707
- return parseBlipFill(blip) ?? { kind: "raw", raw: makeSidecar("a:blipFill", blip, nextId) };
8204
+ Object.assign(next, patch.set);
8205
+ return Object.keys(next).length > 0 ? next : void 0;
8206
+ }
8207
+ function assertEditableTextRunProperties(properties) {
8208
+ for (const property of Object.keys(properties)) {
8209
+ assertEditableTextRunPropertyName(property);
7708
8210
  }
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) };
8211
+ for (const property of EDITABLE_TEXT_RUN_PROPERTIES) {
8212
+ validateEditableTextRunProperty(property, properties[property]);
7713
8213
  }
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
- }
8214
+ }
8215
+ function assertEditableParagraphProperties(properties) {
8216
+ for (const property of Object.keys(properties)) {
8217
+ assertEditableParagraphPropertyName(property);
7718
8218
  }
7719
- return void 0;
8219
+ validateParagraphAlign(properties.align);
8220
+ validateParagraphLevel(properties.level);
8221
+ validateParagraphBullet(properties.bullet);
7720
8222
  }
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
- });
8223
+ function requireBooleanOrUndefined(value, fieldName) {
8224
+ if (value !== void 0 && typeof value !== "boolean") {
8225
+ throw new Error(`updateTextRunProperties: ${fieldName} must be a boolean value`);
7730
8226
  }
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
- };
8227
+ }
8228
+ function assertEditableTextRunPropertyNames(properties) {
8229
+ for (const property of properties) {
8230
+ assertEditableTextRunPropertyName(property);
7746
8231
  }
7747
- return {
7748
- kind: "gradient",
7749
- gradientType: "linear",
7750
- stops,
7751
- angle: asOoxmlAngle(numericAttr2(getChild(grad, "lin"), "ang") ?? 0)
7752
- };
7753
8232
  }
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
- };
8233
+ function assertEditableParagraphPropertyNames(properties) {
8234
+ for (const property of properties) {
8235
+ assertEditableParagraphPropertyName(property);
8236
+ }
7764
8237
  }
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
- };
8238
+ function definedEditableTextRunProperties(properties) {
8239
+ const defined = {};
8240
+ for (const property of EDITABLE_TEXT_RUN_PROPERTIES) {
8241
+ copyDefinedEditableTextRunProperty(defined, properties, property);
8242
+ }
8243
+ return defined;
7776
8244
  }
7777
- function parseRectangleAlignment(value, fallback) {
7778
- return parseEnumValueWithDefault(value, RECTANGLE_ALIGNMENT_TOKENS, fallback);
8245
+ function definedEditableParagraphProperties(properties) {
8246
+ const defined = {};
8247
+ for (const property of EDITABLE_PARAGRAPH_PROPERTIES) {
8248
+ copyDefinedEditableParagraphProperty(defined, properties, property);
8249
+ }
8250
+ return defined;
7779
8251
  }
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
- };
8252
+ function assertEditableTextRunPropertyName(property) {
8253
+ if (!isEditableTextRunProperty(property)) {
8254
+ throw new Error(`updateTextRunProperties: unsupported text run property '${property}'`);
8255
+ }
7790
8256
  }
7791
- function parseOutline(spPr, nextId) {
7792
- const ln = getChild(spPr, "ln");
7793
- return parseLine(ln, nextId);
8257
+ function assertEditableParagraphPropertyName(property) {
8258
+ if (!EDITABLE_PARAGRAPH_PROPERTY_SET.has(property)) {
8259
+ throw new Error(`updateParagraphProperties: unsupported paragraph property '${property}'`);
8260
+ }
7794
8261
  }
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
- };
8262
+ function isEditableTextRunProperty(property) {
8263
+ return EDITABLE_TEXT_RUN_PROPERTY_SET.has(property);
7815
8264
  }
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;
8265
+ function validateParagraphAlign(value) {
8266
+ if (value !== void 0 && !TEXT_ALIGN_VALUES.has(value)) {
8267
+ throw new Error("updateParagraphProperties: align must be left, center, right, or justify");
7827
8268
  }
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
- });
8269
+ }
8270
+ function validateParagraphLevel(value) {
8271
+ if (value !== void 0 && (!Number.isInteger(value) || value < 0 || value > 8)) {
8272
+ throw new Error("updateParagraphProperties: level must be an integer from 0 to 8");
8273
+ }
8274
+ }
8275
+ function validateParagraphBullet(value) {
8276
+ if (value === void 0) return;
8277
+ if (value.type === "none") return;
8278
+ if (value.type === "char") {
8279
+ if (typeof value.char !== "string" || value.char.length === 0) {
8280
+ throw new Error("updateParagraphProperties: bullet.char must be a non-empty string");
7859
8281
  }
8282
+ return;
7860
8283
  }
7861
- return transforms.length > 0 ? { ...base, transforms } : base;
8284
+ if (value.type === "autoNum") {
8285
+ if (!AUTO_NUM_SCHEMES.has(value.scheme)) {
8286
+ throw new Error("updateParagraphProperties: unsupported bullet auto-numbering scheme");
8287
+ }
8288
+ if (!Number.isInteger(value.startAt) || value.startAt < 1) {
8289
+ throw new Error("updateParagraphProperties: bullet.startAt must be a positive integer");
8290
+ }
8291
+ return;
8292
+ }
8293
+ throw new Error("updateParagraphProperties: unsupported bullet type");
7862
8294
  }
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;
8295
+ function validateEditableTextRunProperty(property, value) {
8296
+ EDITABLE_TEXT_RUN_PROPERTY_VALIDATORS[property](value);
7868
8297
  }
7869
- function isTrue(value) {
7870
- return value === "1" || value === "true";
8298
+ function copyDefinedEditableParagraphProperty(target, source, property) {
8299
+ const value = source[property];
8300
+ if (value !== void 0) {
8301
+ target[property] = value;
8302
+ }
7871
8303
  }
7872
- function parseDashStyle(prstDash) {
7873
- const value = getAttr(prstDash, "val");
7874
- return parseEnumValue(value, DASH_STYLES);
8304
+ function copyDefinedEditableTextRunProperty(target, source, property) {
8305
+ const value = source[property];
8306
+ if (value !== void 0) {
8307
+ target[property] = value;
8308
+ }
7875
8309
  }
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
- ]);
8310
+ function textRunPropertiesEqual(left, right) {
8311
+ return stableValueEqual2(left ?? {}, right ?? {});
7884
8312
  }
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;
8313
+ function paragraphPropertiesEqual(left, right) {
8314
+ return stableValueEqual2(left ?? {}, right ?? {});
7892
8315
  }
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;
8316
+ function stableValueEqual2(left, right) {
8317
+ if (Object.is(left, right)) return true;
8318
+ if (Array.isArray(left) || Array.isArray(right)) {
8319
+ if (!Array.isArray(left) || !Array.isArray(right)) return false;
8320
+ if (left.length !== right.length) return false;
8321
+ return left.every((value, index) => stableValueEqual2(value, right[index]));
8322
+ }
8323
+ if (isPlainRecord2(left) || isPlainRecord2(right)) {
8324
+ if (!isPlainRecord2(left) || !isPlainRecord2(right)) return false;
8325
+ const leftKeys = Object.keys(left).sort();
8326
+ const rightKeys = Object.keys(right).sort();
8327
+ if (!stableValueEqual2(leftKeys, rightKeys)) return false;
8328
+ return leftKeys.every((key) => stableValueEqual2(left[key], right[key]));
8329
+ }
8330
+ return false;
7898
8331
  }
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";
8332
+ function isPlainRecord2(value) {
8333
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8334
+ }
8335
+ function createReplacementRunHandle(paragraph) {
8336
+ if (paragraph.runs[0]?.handle !== void 0) return paragraph.runs[0].handle;
8337
+ if (paragraph.handle?.nodeId === void 0) return void 0;
7905
8338
  return {
7906
- type,
7907
- width: parseEnumValueWithDefault(width, ARROW_SIZES2, "med"),
7908
- length: parseEnumValueWithDefault(length, ARROW_SIZES2, "med")
8339
+ ...paragraph.handle,
8340
+ nodeId: asSourceNodeId(`${paragraph.handle.nodeId}:r:0`),
8341
+ orderingSlot: 0
7909
8342
  };
7910
8343
  }
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"]);
8344
+ function asEmu2(value) {
8345
+ return unsafeBrandAssertion2(value);
8346
+ }
8347
+ function asPt(value) {
8348
+ return unsafeBrandAssertion2(value);
8349
+ }
8350
+ function asHundredthPt2(value) {
8351
+ return unsafeBrandAssertion2(value);
8352
+ }
8353
+ function asOoxmlPercent(value) {
8354
+ return unsafeBrandAssertion2(value);
8355
+ }
8356
+ function asOoxmlAngle(value) {
8357
+ return unsafeBrandAssertion2(value);
8358
+ }
8359
+ var textEncoder = new TextEncoder();
8360
+ var ROOT_PART = asPartPath("");
8361
+ var PRESENTATION_PART = asPartPath("ppt/presentation.xml");
8362
+ var SLIDE_PART = asPartPath("ppt/slides/slide1.xml");
8363
+ var SLIDE_LAYOUT_PART = asPartPath("ppt/slideLayouts/slideLayout1.xml");
8364
+ var SLIDE_MASTER_PART = asPartPath("ppt/slideMasters/slideMaster1.xml");
8365
+ var THEME_PART = asPartPath("ppt/theme/theme1.xml");
8366
+ var APP_PROPS_PART = asPartPath("docProps/app.xml");
8367
+ var CORE_PROPS_PART = asPartPath("docProps/core.xml");
7929
8368
  var DEFAULT_COLOR_MAP = {
7930
8369
  bg1: "lt1",
7931
8370
  tx1: "dk1",
@@ -8489,7 +8928,7 @@ function computeConnectorElement(context, connector, layer, partPath) {
8489
8928
  sourceNode: connector,
8490
8929
  ...connector.transform !== void 0 ? { transform: connector.transform } : {},
8491
8930
  ...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) } : {},
8931
+ ...computedOutlineProperty(context, connector.outline, connector.style?.lineRef, partPath),
8493
8932
  ...effects !== void 0 ? { effects } : {}
8494
8933
  };
8495
8934
  }
@@ -8533,7 +8972,7 @@ function computeShapeElement(context, shape, layer, partPath) {
8533
8972
  ...transform !== void 0 ? { transform } : {},
8534
8973
  ...geometry !== void 0 ? { geometry } : {},
8535
8974
  ...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) } : {},
8975
+ ...computedOutlineProperty(context, shape.outline, shape.style?.lineRef, partPath),
8537
8976
  ...effects !== void 0 ? { effects } : {},
8538
8977
  ...shape.textBody !== void 0 ? {
8539
8978
  textBody: computeTextBody(
@@ -8548,7 +8987,7 @@ function computeShapeElement(context, shape, layer, partPath) {
8548
8987
  }
8549
8988
  function computeImageElement(context, image, layer, partPath) {
8550
8989
  const relationship = resolveComputedRelationships(context.source, partPath).find(
8551
- (rel) => rel.id === image.blipRelationshipId && rel.type === IMAGE_REL_TYPE2
8990
+ (rel2) => rel2.id === image.blipRelationshipId && rel2.type === IMAGE_REL_TYPE2
8552
8991
  );
8553
8992
  const effects = image.effects !== void 0 ? computeEffectList(context, image.effects) : void 0;
8554
8993
  const blipEffects = image.blipEffects !== void 0 ? computeBlipEffects(context, image.blipEffects) : void 0;
@@ -8579,7 +9018,7 @@ function computeTableElement(context, table, layer, partPath) {
8579
9018
  }
8580
9019
  function computeChartElement(context, chart, layer, partPath) {
8581
9020
  const relationship = context.relationships.find(
8582
- (rel) => rel.id === chart.chartRelationshipId && CHART_REL_TYPES.has(rel.type)
9021
+ (rel2) => rel2.id === chart.chartRelationshipId && CHART_REL_TYPES.has(rel2.type)
8583
9022
  );
8584
9023
  const chartXml = relationship?.targetPartPath !== void 0 ? readRawPackageText(context.source, relationship.targetPartPath) : void 0;
8585
9024
  const chartData = chartXml !== void 0 ? parseComputedChartData(chartXml, context) : void 0;
@@ -8596,11 +9035,11 @@ function computeChartElement(context, chart, layer, partPath) {
8596
9035
  }
8597
9036
  function computeSmartArtElement(context, smartArt, layer, partPath) {
8598
9037
  const dataRelationship = context.relationships.find(
8599
- (rel) => rel.id === smartArt.dataRelationshipId && DIAGRAM_DATA_REL_TYPES.has(rel.type)
9038
+ (rel2) => rel2.id === smartArt.dataRelationshipId && DIAGRAM_DATA_REL_TYPES.has(rel2.type)
8600
9039
  );
8601
9040
  const dataRelationships = dataRelationship?.targetPartPath !== void 0 ? resolveComputedRelationships(context.source, dataRelationship.targetPartPath) : [];
8602
9041
  const drawingRelationship = dataRelationships.find(
8603
- (rel) => DIAGRAM_DRAWING_REL_TYPES.has(rel.type)
9042
+ (rel2) => DIAGRAM_DRAWING_REL_TYPES.has(rel2.type)
8604
9043
  );
8605
9044
  const drawingPartPath = drawingRelationship?.targetPartPath;
8606
9045
  const drawingXml = drawingPartPath !== void 0 ? readRawPackageText(context.source, drawingPartPath) : void 0;
@@ -8746,7 +9185,7 @@ function computeFill(context, fill, partPath) {
8746
9185
  };
8747
9186
  case "image": {
8748
9187
  const relationship = resolveComputedRelationships(context.source, partPath).find(
8749
- (rel) => rel.id === fill.blipRelationshipId && rel.type === IMAGE_REL_TYPE2
9188
+ (rel2) => rel2.id === fill.blipRelationshipId && rel2.type === IMAGE_REL_TYPE2
8750
9189
  );
8751
9190
  return {
8752
9191
  kind: "image",
@@ -8771,6 +9210,24 @@ function computeOutline(context, outline, partPath) {
8771
9210
  ...outline.fill !== void 0 ? { fill: computeFill(context, outline.fill, partPath) } : {}
8772
9211
  };
8773
9212
  }
9213
+ function computedOutlineProperty(context, outline, lineRef, partPath) {
9214
+ const styleOutline = lineRef !== void 0 ? resolveLineReference(context, lineRef, partPath) : void 0;
9215
+ if (outline === void 0) {
9216
+ return styleOutline !== void 0 ? { outline: styleOutline } : {};
9217
+ }
9218
+ const computed = mergeComputedOutline(styleOutline, computeOutline(context, outline, partPath));
9219
+ return { outline: computed };
9220
+ }
9221
+ function mergeComputedOutline(base, override) {
9222
+ if (base === void 0) return override;
9223
+ const width = override.width ?? base.width;
9224
+ const fill = override.fill ?? base.fill;
9225
+ return {
9226
+ source: { ...base.source, ...override.source },
9227
+ ...width !== void 0 ? { width } : {},
9228
+ ...fill !== void 0 ? { fill } : {}
9229
+ };
9230
+ }
8774
9231
  function resolveFillReference(context, ref, partPath) {
8775
9232
  if (ref.index === 0) return void 0;
8776
9233
  const list = ref.index >= 1e3 ? context.theme?.formatScheme?.backgroundFillStyles : context.theme?.formatScheme?.fillStyles;
@@ -9359,7 +9816,7 @@ var SLIDE_REL_TYPE2 = "http://schemas.openxmlformats.org/officeDocument/2006/rel
9359
9816
  var SLIDE_LAYOUT_REL_TYPE2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout";
9360
9817
  var SLIDE_MASTER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster";
9361
9818
  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";
9819
+ var PRESENTATION_CONTENT_TYPE2 = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
9363
9820
  var textDecoder3 = new TextDecoder();
9364
9821
  function readPptx(input) {
9365
9822
  const entries = unzipPackage(input);
@@ -9526,15 +9983,15 @@ function parsePartRoot(entries, partPath, rootLocalName, diagnostics, includeOrd
9526
9983
  return { root, orderedRoot };
9527
9984
  }
9528
9985
  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");
9986
+ const rels = relationships.find((rel2) => rel2.sourcePartPath === sourcePart)?.relationships;
9987
+ const match = rels?.find((rel2) => rel2.type === relType && rel2.targetMode !== "External");
9531
9988
  if (match === void 0) return void 0;
9532
9989
  return resolveInternalRelationshipTarget(sourcePart, match);
9533
9990
  }
9534
9991
  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);
9992
+ const rels = relationships.find((rel2) => rel2.sourcePartPath === sourcePart)?.relationships ?? [];
9993
+ return rels.filter((rel2) => rel2.type === relType && rel2.targetMode !== "External").flatMap((rel2) => {
9994
+ const target = resolveInternalRelationshipTarget(sourcePart, rel2);
9538
9995
  return target === void 0 ? [] : [target];
9539
9996
  });
9540
9997
  }
@@ -9623,7 +10080,7 @@ function readPresentation(entries, relationships, overrides, diagnostics) {
9623
10080
  const slideSize = readSlideSize(root);
9624
10081
  const defaultTextStyle = parseTextStyle(getChild(root, "defaultTextStyle"));
9625
10082
  const presentationRels = relationships.find(
9626
- (rel) => rel.sourcePartPath === presentationPath
10083
+ (rel2) => rel2.sourcePartPath === presentationPath
9627
10084
  )?.relationships;
9628
10085
  const slidePartPaths = [];
9629
10086
  const sldIdLst = getChild(root, "sldIdLst");
@@ -9631,7 +10088,7 @@ function readPresentation(entries, relationships, overrides, diagnostics) {
9631
10088
  const relId = getNamespacedAttr(sldId, "id");
9632
10089
  if (relId === void 0) continue;
9633
10090
  const handle = { partPath: presentationPartPath, relationshipId: asRelationshipId(relId) };
9634
- const relationship = presentationRels?.find((rel) => rel.id === relId);
10091
+ const relationship = presentationRels?.find((rel2) => rel2.id === relId);
9635
10092
  if (relationship === void 0) {
9636
10093
  diagnostics.push({
9637
10094
  severity: "warning",
@@ -9674,15 +10131,15 @@ function readSlideSize(presentationRoot) {
9674
10131
  }
9675
10132
  function locatePresentationPart(relationships, overrides) {
9676
10133
  const rootRels = relationships.find(
9677
- (rel) => rel.sourcePartPath === PACKAGE_ROOT_PART
10134
+ (rel2) => rel2.sourcePartPath === PACKAGE_ROOT_PART
9678
10135
  )?.relationships;
9679
10136
  const officeDocumentRel = rootRels?.find(
9680
- (rel) => rel.type === OFFICE_DOCUMENT_REL_TYPE && rel.targetMode !== "External"
10137
+ (rel2) => rel2.type === OFFICE_DOCUMENT_REL_TYPE && rel2.targetMode !== "External"
9681
10138
  );
9682
10139
  if (officeDocumentRel !== void 0) {
9683
10140
  return resolveRelationshipTarget(PACKAGE_ROOT_PART, officeDocumentRel.target);
9684
10141
  }
9685
- const override = overrides.find((entry) => entry.contentType === PRESENTATION_CONTENT_TYPE);
10142
+ const override = overrides.find((entry) => entry.contentType === PRESENTATION_CONTENT_TYPE2);
9686
10143
  return override?.partName;
9687
10144
  }
9688
10145
  var MEDIA_CONTENT_TYPE_PREFIXES = ["image/", "audio/", "video/"];
@@ -9710,9 +10167,9 @@ function extensionOf(path) {
9710
10167
  function stripLeadingSlash(path) {
9711
10168
  return path.startsWith("/") ? path.slice(1) : path;
9712
10169
  }
9713
- function parseShapeLocator(handle) {
10170
+ function parseShapeLocator(handle, editName = "shape edit") {
9714
10171
  if (handle.nodeId !== void 0) return { nodeId: String(handle.nodeId) };
9715
- throw new Error("writePptx: shape transform edit requires nodeId in handle");
10172
+ throw new Error(`writePptx: ${editName} requires nodeId in handle`);
9716
10173
  }
9717
10174
  function parseTextRunLocator(nodeId) {
9718
10175
  const value = String(nodeId ?? "");
@@ -9779,19 +10236,21 @@ function locateShapeTreeNode(spTree, locator) {
9779
10236
  function deleteShapeXml(spTree, nodeId) {
9780
10237
  if (spTree === void 0) return false;
9781
10238
  const entry = Object.entries(spTree).find(
9782
- ([key2]) => !key2.startsWith("@_") && localName(key2) === "sp"
10239
+ ([key2, value2]) => !key2.startsWith("@_") && (localName(key2) === "sp" || localName(key2) === "cxnSp") && getShapeTreeNodes(value2).some((shape) => getShapeTreeNodeId(shape) === nodeId)
9783
10240
  );
9784
10241
  if (entry === void 0) return false;
9785
10242
  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
- );
10243
+ const shapes = getShapeTreeNodes(value);
10244
+ const nextShapes = shapes.filter((shape) => getShapeTreeNodeId(shape) !== nodeId);
9790
10245
  if (nextShapes.length === shapes.length) return false;
9791
10246
  if (nextShapes.length === 0) delete spTree[key];
9792
10247
  else spTree[key] = Array.isArray(value) ? nextShapes : nextShapes[0];
9793
10248
  return true;
9794
10249
  }
10250
+ function getShapeTreeNodes(value) {
10251
+ const items = Array.isArray(value) ? unsafeOoxmlBoundaryAssertion(value) : [value];
10252
+ return items.map((item) => unsafeOoxmlBoundaryAssertion(item));
10253
+ }
9795
10254
  function getShapeByOrderingSlot(spTree, orderingSlot) {
9796
10255
  if (!spTree) return void 0;
9797
10256
  let currentSlot = 0;
@@ -9930,7 +10389,7 @@ function textRequiresPreserve(text) {
9930
10389
  return text.startsWith(" ") || text.endsWith(" ");
9931
10390
  }
9932
10391
  var XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
9933
- var textEncoder = new TextEncoder();
10392
+ var textEncoder2 = new TextEncoder();
9934
10393
  var textDecoder4 = new TextDecoder();
9935
10394
  var xmlBuilder2 = new XMLBuilder2({
9936
10395
  ignoreAttributes: false,
@@ -9939,8 +10398,16 @@ var xmlBuilder2 = new XMLBuilder2({
9939
10398
  suppressEmptyNode: true
9940
10399
  });
9941
10400
  function encodeXml(xml) {
9942
- return textEncoder.encode(xml);
10401
+ return textEncoder2.encode(xml);
9943
10402
  }
10403
+ var FILL_CHILD_LOCAL_NAMES = /* @__PURE__ */ new Set([
10404
+ "noFill",
10405
+ "solidFill",
10406
+ "gradFill",
10407
+ "blipFill",
10408
+ "pattFill",
10409
+ "grpFill"
10410
+ ]);
9944
10411
  function serializeDirtyXmlPart(source, partPath, edits) {
9945
10412
  const rawPart = source.packageGraph.rawParts?.find((part) => part.partPath === partPath);
9946
10413
  if (rawPart === void 0) {
@@ -9964,12 +10431,21 @@ function applyDirtyPartEdit(root, edit) {
9964
10431
  case "updateTextRunProperties":
9965
10432
  applyTextRunPropertiesEdit(root, edit);
9966
10433
  return;
10434
+ case "updateParagraphProperties":
10435
+ applyParagraphPropertiesEdit(root, edit);
10436
+ return;
9967
10437
  case "replaceParagraphPlainText":
9968
10438
  applyParagraphTextEdit(root, edit);
9969
10439
  return;
9970
10440
  case "updateShapeTransform":
9971
10441
  applyShapeTransformEdit(root, edit);
9972
10442
  return;
10443
+ case "updateShapeFill":
10444
+ applyShapeFillEdit(root, edit);
10445
+ return;
10446
+ case "updateShapeOutline":
10447
+ applyShapeOutlineEdit(root, edit);
10448
+ return;
9973
10449
  case "addTextBox":
9974
10450
  applyAddTextBoxEdit(root, edit);
9975
10451
  return;
@@ -9982,6 +10458,7 @@ function applyDirtyPartEdit(root, edit) {
9982
10458
  case "replaceImage":
9983
10459
  case "addEmptySlideFromLayout":
9984
10460
  case "duplicateSlide":
10461
+ case "moveSlide":
9985
10462
  case "deleteSlide":
9986
10463
  throw new Error(`writePptx: edit kind '${edit.kind}' does not patch a dirty XML part`);
9987
10464
  }
@@ -10048,6 +10525,34 @@ function applyParagraphTextEdit(root, edit) {
10048
10525
  }
10049
10526
  replaceParagraphRunsWithSingleTextRun(paragraph, edit.text);
10050
10527
  }
10528
+ function applyParagraphPropertiesEdit(root, edit) {
10529
+ assertParagraphPropertiesEdit(edit);
10530
+ const locator = parseParagraphLocator(edit.handle.nodeId);
10531
+ const slide = getChild(root, "sld");
10532
+ const cSld = getChild(slide, "cSld");
10533
+ const spTree = getChild(cSld, "spTree");
10534
+ const shape = locateShape(spTree, locator);
10535
+ const paragraphs = getChildArray(getChild(shape, "txBody"), "p");
10536
+ const target = locateParagraphPropertiesForEdit(paragraphs, locator);
10537
+ if (target === void 0) {
10538
+ throw new Error(
10539
+ `writePptx: paragraph properties handle '${edit.handle.nodeId}' no longer matches source XML`
10540
+ );
10541
+ }
10542
+ const set = edit.set ?? {};
10543
+ const hasSet = hasParagraphPropertiesSetValues(set);
10544
+ const existingParagraphProperties = target.properties;
10545
+ if (existingParagraphProperties === void 0 && !hasSet) return;
10546
+ const pPr = existingParagraphProperties ?? ensureParagraphProperties(target.paragraph);
10547
+ let cleared = false;
10548
+ for (const property of edit.clear ?? []) {
10549
+ cleared = clearParagraphProperty(pPr, property) || cleared;
10550
+ }
10551
+ if (set.align !== void 0) pPr["@_algn"] = paragraphAlignOoxmlValue(set.align);
10552
+ if (set.level !== void 0) pPr["@_lvl"] = String(set.level);
10553
+ if (set.bullet !== void 0) setParagraphBullet(pPr, set.bullet);
10554
+ if (!hasSet && cleared && xmlNodeIsEmpty(pPr)) deleteParagraphProperties(target.paragraph, pPr);
10555
+ }
10051
10556
  function locateTextRun(root, nodeId) {
10052
10557
  const locator = parseTextRunLocator(nodeId);
10053
10558
  const slide = getChild(root, "sld");
@@ -10059,7 +10564,7 @@ function locateTextRun(root, nodeId) {
10059
10564
  return getChildArray(paragraph, "r")[locator.runIndex];
10060
10565
  }
10061
10566
  function applyShapeTransformEdit(root, edit) {
10062
- const locator = parseShapeLocator(edit.handle);
10567
+ const locator = parseShapeLocator(edit.handle, "shape transform edit");
10063
10568
  const slide = getChild(root, "sld");
10064
10569
  const cSld = getChild(slide, "cSld");
10065
10570
  const spTree = getChild(cSld, "spTree");
@@ -10082,6 +10587,22 @@ function applyShapeTransformEdit(root, edit) {
10082
10587
  ext["@_cx"] = String(edit.width);
10083
10588
  ext["@_cy"] = String(edit.height);
10084
10589
  }
10590
+ function applyShapeFillEdit(root, edit) {
10591
+ const shape = locateEditableShapeTreeNode(root, edit.handle, "shape fill edit");
10592
+ if (shape.localName === "cxnSp") {
10593
+ throw new Error(
10594
+ `writePptx: shape fill handle '${String(edit.handle.nodeId)}' references a connector`
10595
+ );
10596
+ }
10597
+ const spPr = ensureShapeProperties(shape.node);
10598
+ replaceFillChild(spPr, edit.fill);
10599
+ }
10600
+ function applyShapeOutlineEdit(root, edit) {
10601
+ const shape = locateEditableShapeTreeNode(root, edit.handle, "shape outline edit");
10602
+ const spPr = ensureShapeProperties(shape.node);
10603
+ const ln = ensureLineProperties(spPr);
10604
+ applyOutlinePatch(ln, edit.outline);
10605
+ }
10085
10606
  function applyAddTextBoxEdit(root, edit) {
10086
10607
  const slide = getChild(root, "sld");
10087
10608
  const cSld = getChild(slide, "cSld");
@@ -10104,22 +10625,133 @@ function applyAddConnectorEdit(root, edit) {
10104
10625
  if (locateShapeTreeNode(spTree, { nodeId: edit.shapeId }) !== void 0) {
10105
10626
  throw new Error(`writePptx: shape id '${edit.shapeId}' already exists in source XML`);
10106
10627
  }
10107
- if (locateShapeTreeNode(spTree, { nodeId: edit.startShapeId }) === void 0) {
10628
+ if (edit.startShapeId !== void 0 && locateShapeTreeNode(spTree, { nodeId: edit.startShapeId }) === void 0) {
10108
10629
  throw new Error(`writePptx: connector start shape '${edit.startShapeId}' was not found`);
10109
10630
  }
10110
- if (locateShapeTreeNode(spTree, { nodeId: edit.endShapeId }) === void 0) {
10631
+ if (edit.endShapeId !== void 0 && locateShapeTreeNode(spTree, { nodeId: edit.endShapeId }) === void 0) {
10111
10632
  throw new Error(`writePptx: connector end shape '${edit.endShapeId}' was not found`);
10112
10633
  }
10113
10634
  appendChild(spTree, "p:cxnSp", parseShapeFragmentXml(edit.xml, "cxnSp"));
10114
10635
  }
10115
10636
  function applyDeleteShapeEdit(root, edit) {
10116
- const locator = parseShapeLocator(edit.handle);
10637
+ const locator = parseShapeLocator(edit.handle, "shape delete edit");
10117
10638
  const slide = getChild(root, "sld");
10118
10639
  const cSld = getChild(slide, "cSld");
10119
10640
  const spTree = getChild(cSld, "spTree");
10120
10641
  if (!deleteShapeXml(spTree, locator.nodeId)) {
10121
- throw new Error(`writePptx: shape delete handle '${locator.nodeId}' no longer matches p:sp`);
10642
+ throw new Error(
10643
+ `writePptx: shape delete handle '${locator.nodeId}' no longer matches p:sp or p:cxnSp`
10644
+ );
10645
+ }
10646
+ }
10647
+ function locateEditableShapeTreeNode(root, handle, editName) {
10648
+ const locator = parseShapeLocator(handle, editName);
10649
+ const slide = getChild(root, "sld");
10650
+ const cSld = getChild(slide, "cSld");
10651
+ const spTree = getChild(cSld, "spTree");
10652
+ const shape = locateShapeTreeNodeWithLocalName(spTree, locator.nodeId);
10653
+ if (shape === void 0) {
10654
+ throw new Error(
10655
+ `writePptx: ${editName} handle '${String(handle.nodeId)}' no longer matches source XML`
10656
+ );
10657
+ }
10658
+ if (shape.localName !== "sp" && shape.localName !== "cxnSp") {
10659
+ throw new Error(
10660
+ `writePptx: ${editName} handle '${String(handle.nodeId)}' does not reference p:sp or p:cxnSp`
10661
+ );
10662
+ }
10663
+ return shape;
10664
+ }
10665
+ function locateShapeTreeNodeWithLocalName(spTree, nodeId) {
10666
+ if (spTree === void 0) return void 0;
10667
+ for (const key of Object.keys(spTree)) {
10668
+ if (key.startsWith("@_")) continue;
10669
+ const keyLocalName = localName(key);
10670
+ const value = spTree[key];
10671
+ const items = Array.isArray(value) ? value : [value];
10672
+ for (const item of items) {
10673
+ const node = unsafeOoxmlBoundaryAssertion(item);
10674
+ const nonVisualProperties = getChild(node, "nvSpPr") ?? getChild(node, "nvPicPr") ?? getChild(node, "nvCxnSpPr") ?? getChild(node, "nvGrpSpPr") ?? getChild(node, "nvGraphicFramePr");
10675
+ if (getChild(nonVisualProperties, "cNvPr")?.["@_id"] === nodeId) {
10676
+ return { node, localName: keyLocalName };
10677
+ }
10678
+ }
10679
+ }
10680
+ return void 0;
10681
+ }
10682
+ function ensureShapeProperties(shape) {
10683
+ const existing = getChild(shape, "spPr");
10684
+ if (existing !== void 0) return existing;
10685
+ const entries = [];
10686
+ let inserted = false;
10687
+ for (const [key, value] of Object.entries(shape)) {
10688
+ entries.push([key, value]);
10689
+ if (!inserted && !key.startsWith("@_") && localName(key).startsWith("nv")) {
10690
+ entries.push(["p:spPr", {}]);
10691
+ inserted = true;
10692
+ }
10693
+ }
10694
+ if (!inserted) entries.push(["p:spPr", {}]);
10695
+ replaceNodeEntries(shape, entries);
10696
+ return getChild(shape, "spPr") ?? {};
10697
+ }
10698
+ function ensureLineProperties(spPr) {
10699
+ const existing = getChild(spPr, "ln");
10700
+ if (existing !== void 0) return existing;
10701
+ insertChildByOrder(
10702
+ spPr,
10703
+ "a:ln",
10704
+ {},
10705
+ (name) => ["effectLst", "effectDag", "scene3d", "sp3d", "extLst"].includes(name)
10706
+ );
10707
+ return getChild(spPr, "ln") ?? {};
10708
+ }
10709
+ function applyOutlinePatch(ln, outline) {
10710
+ if (outline.width !== void 0) ln["@_w"] = String(outline.width);
10711
+ if (outline.fill !== void 0) replaceFillChild(ln, outline.fill);
10712
+ }
10713
+ function replaceFillChild(parent, fill) {
10714
+ const fillNode = fill.kind === "none" ? { key: "a:noFill", value: {} } : {
10715
+ key: "a:solidFill",
10716
+ value: { "a:srgbClr": { "@_val": fill.color.hex.toUpperCase() } }
10717
+ };
10718
+ const entries = Object.entries(parent).filter(
10719
+ ([key]) => key.startsWith("@_") || !FILL_CHILD_LOCAL_NAMES.has(localName(key))
10720
+ );
10721
+ replaceNodeEntries(parent, entries);
10722
+ insertChildByOrder(
10723
+ parent,
10724
+ fillNode.key,
10725
+ fillNode.value,
10726
+ (name) => [
10727
+ "ln",
10728
+ "effectLst",
10729
+ "effectDag",
10730
+ "scene3d",
10731
+ "sp3d",
10732
+ "extLst",
10733
+ "prstDash",
10734
+ "custDash",
10735
+ "round",
10736
+ "bevel",
10737
+ "miter",
10738
+ "headEnd",
10739
+ "tailEnd"
10740
+ ].includes(name)
10741
+ );
10742
+ }
10743
+ function insertChildByOrder(node, key, value, shouldInsertBefore) {
10744
+ const entries = [];
10745
+ let inserted = false;
10746
+ for (const [entryKey, entryValue] of Object.entries(node)) {
10747
+ if (!inserted && !entryKey.startsWith("@_") && shouldInsertBefore(localName(entryKey))) {
10748
+ entries.push([key, value]);
10749
+ inserted = true;
10750
+ }
10751
+ entries.push([entryKey, entryValue]);
10122
10752
  }
10753
+ if (!inserted) entries.push([key, value]);
10754
+ replaceNodeEntries(node, entries);
10123
10755
  }
10124
10756
  function parseShapeFragmentXml(xml, rootLocalName) {
10125
10757
  const node = getChild(parseXml(xml), rootLocalName);
@@ -10181,12 +10813,104 @@ function booleanOoxmlValue(value) {
10181
10813
  function hasTextRunPropertiesSetValues(properties) {
10182
10814
  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
10815
  }
10816
+ function hasParagraphPropertiesSetValues(properties) {
10817
+ return properties.align !== void 0 || properties.level !== void 0 || properties.bullet !== void 0;
10818
+ }
10184
10819
  function assertTextRunPropertiesEdit(edit) {
10185
10820
  const clear = edit.clear ?? [];
10186
10821
  if (!hasTextRunPropertiesSetValues(edit.set ?? {}) && clear.length === 0) {
10187
10822
  throw new Error("writePptx: text run properties edit must set or clear at least one property");
10188
10823
  }
10189
10824
  }
10825
+ function assertParagraphPropertiesEdit(edit) {
10826
+ const clear = edit.clear ?? [];
10827
+ if (!hasParagraphPropertiesSetValues(edit.set ?? {}) && clear.length === 0) {
10828
+ throw new Error("writePptx: paragraph properties edit must set or clear at least one property");
10829
+ }
10830
+ }
10831
+ function locateParagraphPropertiesForEdit(paragraphs, locator) {
10832
+ let logicalParagraphIndex = 0;
10833
+ for (const paragraph of paragraphs) {
10834
+ const logicalCount = getLogicalParagraphCount(paragraph);
10835
+ if (locator.paragraphIndex >= logicalParagraphIndex && locator.paragraphIndex < logicalParagraphIndex + logicalCount) {
10836
+ if (logicalCount === 1) {
10837
+ return { paragraph, properties: getChild(paragraph, "pPr") };
10838
+ }
10839
+ const relativeIndex = locator.paragraphIndex - logicalParagraphIndex;
10840
+ return {
10841
+ paragraph,
10842
+ properties: getBulletParagraphProperties(paragraph)[relativeIndex]
10843
+ };
10844
+ }
10845
+ logicalParagraphIndex += logicalCount;
10846
+ }
10847
+ return void 0;
10848
+ }
10849
+ function getBulletParagraphProperties(paragraph) {
10850
+ return getChildArray(paragraph, "pPr").filter(
10851
+ (properties) => getChild(properties, "buChar") !== void 0 || getChild(properties, "buAutoNum") !== void 0
10852
+ );
10853
+ }
10854
+ function ensureParagraphProperties(paragraph) {
10855
+ const existing = getChild(paragraph, "pPr");
10856
+ if (existing !== void 0) return existing;
10857
+ const entries = [];
10858
+ let inserted = false;
10859
+ for (const [key, value] of Object.entries(paragraph)) {
10860
+ if (!inserted && !key.startsWith("@_")) {
10861
+ entries.push(["a:pPr", {}]);
10862
+ inserted = true;
10863
+ }
10864
+ entries.push([key, value]);
10865
+ }
10866
+ if (!inserted) entries.push(["a:pPr", {}]);
10867
+ replaceNodeEntries(paragraph, entries);
10868
+ return getChild(paragraph, "pPr") ?? {};
10869
+ }
10870
+ function deleteParagraphProperties(paragraph, pPr) {
10871
+ if (getChild(paragraph, "pPr") === pPr) deleteChild(paragraph, "pPr");
10872
+ }
10873
+ function clearParagraphProperty(pPr, property) {
10874
+ switch (property) {
10875
+ case "align":
10876
+ if (pPr["@_algn"] === void 0) return false;
10877
+ delete pPr["@_algn"];
10878
+ return true;
10879
+ case "level":
10880
+ if (pPr["@_lvl"] === void 0) return false;
10881
+ delete pPr["@_lvl"];
10882
+ return true;
10883
+ case "bullet":
10884
+ return deleteParagraphBullet(pPr);
10885
+ }
10886
+ }
10887
+ function deleteParagraphBullet(pPr) {
10888
+ const deletedNone = deleteChild(pPr, "buNone");
10889
+ const deletedChar = deleteChild(pPr, "buChar");
10890
+ const deletedAutoNum = deleteChild(pPr, "buAutoNum");
10891
+ return deletedNone || deletedChar || deletedAutoNum;
10892
+ }
10893
+ function setParagraphBullet(pPr, bullet) {
10894
+ deleteParagraphBullet(pPr);
10895
+ if (bullet.type === "none") {
10896
+ replaceChild(pPr, "buNone", {});
10897
+ return;
10898
+ }
10899
+ if (bullet.type === "char") {
10900
+ replaceChild(pPr, "buChar", { "@_char": bullet.char });
10901
+ return;
10902
+ }
10903
+ replaceChild(pPr, "buAutoNum", {
10904
+ "@_type": bullet.scheme,
10905
+ "@_startAt": String(bullet.startAt)
10906
+ });
10907
+ }
10908
+ function paragraphAlignOoxmlValue(align) {
10909
+ if (align === "center") return "ctr";
10910
+ if (align === "right") return "r";
10911
+ if (align === "justify") return "just";
10912
+ return "l";
10913
+ }
10190
10914
  function replaceParagraphRunsWithSingleTextRun(paragraph, text) {
10191
10915
  const firstRunProperties = getChild(getFirstRunLikeNode(paragraph), "rPr");
10192
10916
  const replacementRun = {
@@ -10255,6 +10979,8 @@ function validateEdits(edits) {
10255
10979
  const runKeys = /* @__PURE__ */ new Set();
10256
10980
  const paragraphKeys = /* @__PURE__ */ new Set();
10257
10981
  const shapeKeys = /* @__PURE__ */ new Set();
10982
+ const shapeFillKeys = /* @__PURE__ */ new Set();
10983
+ const shapeOutlineKeys = /* @__PURE__ */ new Set();
10258
10984
  const deletedShapeKeys = /* @__PURE__ */ new Set();
10259
10985
  const textRunEdits = [];
10260
10986
  const textRunPropertiesEdits = [];
@@ -10283,6 +11009,8 @@ function validateEdits(edits) {
10283
11009
  case "updateTextRunProperties":
10284
11010
  textRunPropertiesEdits.push(edit);
10285
11011
  break;
11012
+ case "updateParagraphProperties":
11013
+ break;
10286
11014
  case "replaceParagraphPlainText": {
10287
11015
  const key = editHandleNodeKey(edit);
10288
11016
  if (paragraphKeys.has(key)) {
@@ -10303,6 +11031,26 @@ function validateEdits(edits) {
10303
11031
  shapeKeys.add(key);
10304
11032
  break;
10305
11033
  }
11034
+ case "updateShapeFill": {
11035
+ const key = editHandleNodeKey(edit);
11036
+ if (shapeFillKeys.has(key)) {
11037
+ throw new Error(
11038
+ `writePptx: conflicting shape fill edits for handle '${String(edit.handle.nodeId)}'`
11039
+ );
11040
+ }
11041
+ shapeFillKeys.add(key);
11042
+ break;
11043
+ }
11044
+ case "updateShapeOutline": {
11045
+ const key = editHandleNodeKey(edit);
11046
+ if (shapeOutlineKeys.has(key)) {
11047
+ throw new Error(
11048
+ `writePptx: conflicting shape outline edits for handle '${String(edit.handle.nodeId)}'`
11049
+ );
11050
+ }
11051
+ shapeOutlineKeys.add(key);
11052
+ break;
11053
+ }
10306
11054
  case "deleteShape": {
10307
11055
  const key = editHandleNodeKey(edit);
10308
11056
  if (deletedShapeKeys.has(key)) {
@@ -10316,6 +11064,7 @@ function validateEdits(edits) {
10316
11064
  case "replaceImage":
10317
11065
  case "addEmptySlideFromLayout":
10318
11066
  case "duplicateSlide":
11067
+ case "moveSlide":
10319
11068
  case "deleteSlide":
10320
11069
  break;
10321
11070
  }
@@ -10422,6 +11171,9 @@ function serializePresentationWithSlideTopologyEdits(source, operations) {
10422
11171
  case "removeSlide":
10423
11172
  removeSlideId(sldIdLst, operation.relationshipId);
10424
11173
  break;
11174
+ case "moveSlide":
11175
+ moveSlideId(sldIdLst, operation.relationshipId, operation.toIndex);
11176
+ break;
10425
11177
  }
10426
11178
  }
10427
11179
  return encodeXml(XML_DECLARATION + xmlBuilder2.build(stripXmlProcessingInstruction(root)));
@@ -10464,6 +11216,24 @@ function removeSlideId(sldIdLst, relationshipId) {
10464
11216
  const { key, items } = slideIdEntries(sldIdLst);
10465
11217
  sldIdLst[key] = items.filter((item) => getRelationshipAttr(item) !== relationshipId);
10466
11218
  }
11219
+ function moveSlideId(sldIdLst, relationshipId, toIndex) {
11220
+ const { key, items } = slideIdEntries(sldIdLst);
11221
+ const fromIndex = items.findIndex((item2) => getRelationshipAttr(item2) === relationshipId);
11222
+ if (fromIndex === -1) {
11223
+ throw new Error(
11224
+ `writePptx: slide relationship '${relationshipId}' was not found in p:sldIdLst`
11225
+ );
11226
+ }
11227
+ if (toIndex < 0 || toIndex >= items.length) {
11228
+ throw new Error(`writePptx: slide move target index '${toIndex}' is out of range`);
11229
+ }
11230
+ if (fromIndex === toIndex) return;
11231
+ const moved = [...items];
11232
+ const [item] = moved.splice(fromIndex, 1);
11233
+ if (item === void 0) return;
11234
+ moved.splice(toIndex, 0, item);
11235
+ sldIdLst[key] = moved;
11236
+ }
10467
11237
  function slideIdEntries(sldIdLst) {
10468
11238
  const key = namespacedChildKey(sldIdLst, "p:sldId", "sldId");
10469
11239
  const value = sldIdLst[key];
@@ -10477,7 +11247,7 @@ function getRelationshipAttr(node) {
10477
11247
  return getNamespacedAttr(node, "id");
10478
11248
  }
10479
11249
  var CONTENT_TYPES_PART2 = "[Content_Types].xml";
10480
- var RELS_CONTENT_TYPE2 = "application/vnd.openxmlformats-package.relationships+xml";
11250
+ var RELS_CONTENT_TYPE3 = "application/vnd.openxmlformats-package.relationships+xml";
10481
11251
  function writePptx(source) {
10482
11252
  const edits = source.edits ?? [];
10483
11253
  validateEdits(edits);
@@ -10524,7 +11294,7 @@ function writePptx(source) {
10524
11294
  }
10525
11295
  for (const part of source.packageGraph.parts) {
10526
11296
  if (written.has(part.partPath)) continue;
10527
- if (part.contentType === RELS_CONTENT_TYPE2 || isRelationshipPart(part.partPath)) continue;
11297
+ if (part.contentType === RELS_CONTENT_TYPE3 || isRelationshipPart(part.partPath)) continue;
10528
11298
  throw new Error(
10529
11299
  "writePptx: no preserved package material for part '" + part.partPath + "'; edited part generation is not implemented in the no-edit writer"
10530
11300
  );
@@ -11411,16 +12181,21 @@ export {
11411
12181
  asSourceNodeId,
11412
12182
  findShapeNodeBySourceHandle,
11413
12183
  updateShapeTransform,
12184
+ setShapeFill,
12185
+ setShapeOutline,
11414
12186
  addTextBox,
11415
12187
  addConnector,
11416
12188
  deleteShape,
11417
12189
  replaceImageBytes,
11418
12190
  addEmptySlideFromLayout,
11419
12191
  duplicateSlide,
12192
+ moveSlide,
11420
12193
  deleteSlide,
11421
12194
  replaceTextRunPlainText,
11422
12195
  setTextRunProperties,
11423
12196
  clearTextRunProperties,
12197
+ setParagraphProperties,
12198
+ clearParagraphProperties,
11424
12199
  replaceParagraphPlainText,
11425
12200
  asEmu2 as asEmu,
11426
12201
  createComputedView,