@pptx-glimpse/document 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,4677 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ asEmu: () => asEmu,
24
+ asHundredthPt: () => asHundredthPt,
25
+ asOoxmlAngle: () => asOoxmlAngle,
26
+ asOoxmlPercent: () => asOoxmlPercent,
27
+ asPartPath: () => asPartPath,
28
+ asPt: () => asPt,
29
+ asRawSidecarId: () => asRawSidecarId,
30
+ asRelationshipId: () => asRelationshipId,
31
+ asSourceNodeId: () => asSourceNodeId,
32
+ createComputedView: () => createComputedView,
33
+ findParagraphBySourceHandle: () => findParagraphBySourceHandle,
34
+ findShapeNodeBySourceHandle: () => findShapeNodeBySourceHandle,
35
+ findTextRunBySourceHandle: () => findTextRunBySourceHandle,
36
+ readPptx: () => readPptx,
37
+ replaceParagraphPlainText: () => replaceParagraphPlainText,
38
+ replaceTextRunPlainText: () => replaceTextRunPlainText,
39
+ updateShapeTransform: () => updateShapeTransform,
40
+ writePptx: () => writePptx
41
+ });
42
+ module.exports = __toCommonJS(index_exports);
43
+
44
+ // src/unsafe-type-assertion.ts
45
+ function unsafeOoxmlBoundaryAssertion(value) {
46
+ return value;
47
+ }
48
+ function unsafeBrandAssertion(value) {
49
+ return value;
50
+ }
51
+
52
+ // src/source/handles.ts
53
+ function asPartPath(value) {
54
+ return unsafeBrandAssertion(value);
55
+ }
56
+ function asRelationshipId(value) {
57
+ return unsafeBrandAssertion(value);
58
+ }
59
+ function asSourceNodeId(value) {
60
+ return unsafeBrandAssertion(value);
61
+ }
62
+ function asRawSidecarId(value) {
63
+ return unsafeBrandAssertion(value);
64
+ }
65
+
66
+ // src/source/editing.ts
67
+ function findTextRunBySourceHandle(source, handle) {
68
+ for (const slide of source.slides) {
69
+ for (const shape of slide.shapes) {
70
+ if (shape.kind !== "shape") continue;
71
+ const run = findTextRunInShape(shape, handle);
72
+ if (run !== void 0) return run;
73
+ }
74
+ }
75
+ return void 0;
76
+ }
77
+ function findParagraphBySourceHandle(source, handle) {
78
+ for (const slide of source.slides) {
79
+ for (const shape of slide.shapes) {
80
+ if (shape.kind !== "shape") continue;
81
+ const paragraph = findParagraphInShape(shape, handle);
82
+ if (paragraph !== void 0) return paragraph;
83
+ }
84
+ }
85
+ return void 0;
86
+ }
87
+ function replaceTextRunPlainText(source, handle, text) {
88
+ let replaced = false;
89
+ const slides = source.slides.map((slide) => ({
90
+ ...slide,
91
+ shapes: slide.shapes.map((shape) => {
92
+ if (shape.kind !== "shape" || shape.textBody === void 0) return shape;
93
+ let shapeChanged = false;
94
+ const paragraphs = shape.textBody.paragraphs.map((paragraph) => {
95
+ let paragraphChanged = false;
96
+ const runs = paragraph.runs.map((run) => {
97
+ if (!sourceHandlesEqual(run.handle, handle)) return run;
98
+ replaced = true;
99
+ paragraphChanged = true;
100
+ shapeChanged = true;
101
+ return { ...run, text };
102
+ });
103
+ return !paragraphChanged ? paragraph : { ...paragraph, runs };
104
+ });
105
+ if (!shapeChanged) return shape;
106
+ return {
107
+ ...shape,
108
+ textBody: {
109
+ ...shape.textBody,
110
+ paragraphs
111
+ }
112
+ };
113
+ })
114
+ }));
115
+ if (!replaced) {
116
+ throw new Error(
117
+ "replaceTextRunPlainText: text run handle was not found in PptxSourceModel source"
118
+ );
119
+ }
120
+ return {
121
+ ...source,
122
+ slides,
123
+ edits: [...source.edits ?? [], { kind: "replaceTextRunPlainText", handle, text }]
124
+ };
125
+ }
126
+ function replaceParagraphPlainText(source, handle, text) {
127
+ let replaced = false;
128
+ const slides = source.slides.map((slide) => ({
129
+ ...slide,
130
+ shapes: slide.shapes.map((shape) => {
131
+ if (shape.kind !== "shape" || shape.textBody === void 0) return shape;
132
+ let shapeChanged = false;
133
+ const paragraphs = shape.textBody.paragraphs.map((paragraph) => {
134
+ if (!sourceHandlesEqual(paragraph.handle, handle)) return paragraph;
135
+ const replacementHandle = createReplacementRunHandle(paragraph);
136
+ replaced = true;
137
+ shapeChanged = true;
138
+ return {
139
+ ...paragraph,
140
+ runs: [
141
+ {
142
+ kind: "textRun",
143
+ text,
144
+ ...paragraph.runs[0]?.properties !== void 0 ? { properties: paragraph.runs[0].properties } : {},
145
+ ...replacementHandle !== void 0 ? { handle: replacementHandle } : {}
146
+ }
147
+ ]
148
+ };
149
+ });
150
+ if (!shapeChanged) return shape;
151
+ return {
152
+ ...shape,
153
+ textBody: {
154
+ ...shape.textBody,
155
+ paragraphs
156
+ }
157
+ };
158
+ })
159
+ }));
160
+ if (!replaced) {
161
+ throw new Error(
162
+ "replaceParagraphPlainText: paragraph handle was not found in PptxSourceModel source"
163
+ );
164
+ }
165
+ return {
166
+ ...source,
167
+ slides,
168
+ edits: [...source.edits ?? [], { kind: "replaceParagraphPlainText", handle, text }]
169
+ };
170
+ }
171
+ function findShapeNodeBySourceHandle(source, handle) {
172
+ for (const slide of source.slides) {
173
+ const shape = findShapeNodeInTree(slide.shapes, handle);
174
+ if (shape !== void 0) return shape;
175
+ }
176
+ return void 0;
177
+ }
178
+ function updateShapeTransform(source, handle, transform) {
179
+ if (handle.nodeId === void 0) {
180
+ throw new Error("updateShapeTransform: shape transform edit requires a node id");
181
+ }
182
+ let updated = false;
183
+ const slides = source.slides.map((slide) => ({
184
+ ...slide,
185
+ shapes: slide.shapes.map((shape) => {
186
+ if (!sourceHandlesEqual(shape.handle, handle)) return shape;
187
+ if (hasAlternateContentSidecar(shape)) {
188
+ throw new Error("updateShapeTransform: shapes inside AlternateContent are not supported");
189
+ }
190
+ if (!hasEditableTransform(shape)) {
191
+ throw new Error("updateShapeTransform: shape handle does not reference a shape with xfrm");
192
+ }
193
+ updated = true;
194
+ return {
195
+ ...shape,
196
+ transform: {
197
+ ...shape.transform,
198
+ offsetX: transform.offsetX,
199
+ offsetY: transform.offsetY,
200
+ width: transform.width,
201
+ height: transform.height
202
+ }
203
+ };
204
+ })
205
+ }));
206
+ if (!updated) {
207
+ if (source.slides.some((slide) => hasNestedShapeNodeWithHandle(slide.shapes, handle))) {
208
+ throw new Error("updateShapeTransform: nested group shape editing is not supported");
209
+ }
210
+ throw new Error("updateShapeTransform: shape handle was not found in PptxSourceModel source");
211
+ }
212
+ return {
213
+ ...source,
214
+ slides,
215
+ edits: [
216
+ ...source.edits ?? [],
217
+ {
218
+ kind: "updateShapeTransform",
219
+ handle,
220
+ offsetX: transform.offsetX,
221
+ offsetY: transform.offsetY,
222
+ width: transform.width,
223
+ height: transform.height
224
+ }
225
+ ]
226
+ };
227
+ }
228
+ function findTextRunInShape(shape, handle) {
229
+ for (const paragraph of shape.textBody?.paragraphs ?? []) {
230
+ for (const run of paragraph.runs) {
231
+ if (sourceHandlesEqual(run.handle, handle)) return run;
232
+ }
233
+ }
234
+ return void 0;
235
+ }
236
+ function findParagraphInShape(shape, handle) {
237
+ return shape.textBody?.paragraphs.find(
238
+ (paragraph) => sourceHandlesEqual(paragraph.handle, handle)
239
+ );
240
+ }
241
+ function createReplacementRunHandle(paragraph) {
242
+ if (paragraph.runs[0]?.handle !== void 0) return paragraph.runs[0].handle;
243
+ if (paragraph.handle?.nodeId === void 0) return void 0;
244
+ return {
245
+ ...paragraph.handle,
246
+ nodeId: asSourceNodeId(`${paragraph.handle.nodeId}:r:0`),
247
+ orderingSlot: 0
248
+ };
249
+ }
250
+ function hasEditableTransform(shape) {
251
+ return shape.kind !== "raw" && shape.transform !== void 0;
252
+ }
253
+ function findShapeNodeInTree(shapes, handle) {
254
+ for (const shape of shapes) {
255
+ if (sourceHandlesEqual(shape.handle, handle)) return shape;
256
+ if (shape.kind === "group") {
257
+ const child = findShapeNodeInTree(shape.children, handle);
258
+ if (child !== void 0) return child;
259
+ }
260
+ }
261
+ return void 0;
262
+ }
263
+ function hasNestedShapeNodeWithHandle(shapes, handle) {
264
+ return shapes.some(
265
+ (shape) => shape.kind === "group" && (findShapeNodeInTree(shape.children, handle) !== void 0 || hasNestedShapeNodeWithHandle(shape.children, handle))
266
+ );
267
+ }
268
+ function hasAlternateContentSidecar(shape) {
269
+ if (shape.kind === "raw") return false;
270
+ return shape.rawSidecars?.some((sidecar) => sidecar.node.name === "mc:AlternateContent") ?? false;
271
+ }
272
+ function sourceHandlesEqual(left, right) {
273
+ if (left === void 0) return false;
274
+ return left.partPath === right.partPath && left.nodeId === right.nodeId && left.relationshipId === right.relationshipId && left.orderingSlot === right.orderingSlot;
275
+ }
276
+
277
+ // src/source/units.ts
278
+ function asEmu(value) {
279
+ return unsafeBrandAssertion(value);
280
+ }
281
+ function asPt(value) {
282
+ return unsafeBrandAssertion(value);
283
+ }
284
+ function asHundredthPt(value) {
285
+ return unsafeBrandAssertion(value);
286
+ }
287
+ function asOoxmlPercent(value) {
288
+ return unsafeBrandAssertion(value);
289
+ }
290
+ function asOoxmlAngle(value) {
291
+ return unsafeBrandAssertion(value);
292
+ }
293
+
294
+ // src/reader/ooxml-values.ts
295
+ function parseEnumValue(value, allowed) {
296
+ return value !== void 0 && allowed.has(unsafeOoxmlBoundaryAssertion(value)) ? unsafeOoxmlBoundaryAssertion(value) : void 0;
297
+ }
298
+ function parseEnumValueWithDefault(value, allowed, fallback) {
299
+ return parseEnumValue(value, allowed) ?? fallback;
300
+ }
301
+
302
+ // src/reader/xml.ts
303
+ var import_fast_xml_parser = require("fast-xml-parser");
304
+ var parser = new import_fast_xml_parser.XMLParser({
305
+ ignoreAttributes: false,
306
+ attributeNamePrefix: "@_",
307
+ parseAttributeValue: false,
308
+ // Retain prefix. See the comment at the beginning of the file for the reason.
309
+ removeNSPrefix: false,
310
+ // Do not trim text run (`a:t`) to preserve significant white space at the beginning and end.
311
+ // The PPTX part has been minified, and the blank text from the indentation between the tags is
312
+ // This does not cause spurious text node contamination.
313
+ trimValues: false
314
+ });
315
+ var orderedParser = new import_fast_xml_parser.XMLParser({
316
+ preserveOrder: true,
317
+ removeNSPrefix: true,
318
+ ignoreAttributes: true,
319
+ trimValues: false
320
+ });
321
+ function parseXml(xml) {
322
+ return unsafeOoxmlBoundaryAssertion(parser.parse(xml));
323
+ }
324
+ function parseXmlOrdered(xml) {
325
+ return unsafeOoxmlBoundaryAssertion(orderedParser.parse(xml));
326
+ }
327
+ function navigateOrdered(ordered, path) {
328
+ let current = ordered;
329
+ for (const key of path) {
330
+ const entry = current.find((item) => key in item);
331
+ const value = entry?.[key];
332
+ if (!Array.isArray(value)) return void 0;
333
+ current = unsafeOoxmlBoundaryAssertion(value);
334
+ }
335
+ return [...current];
336
+ }
337
+ function localName(key) {
338
+ const colon = key.indexOf(":");
339
+ return colon === -1 ? key : key.slice(colon + 1);
340
+ }
341
+ function getChild(node, name) {
342
+ if (!node) return void 0;
343
+ for (const key of Object.keys(node)) {
344
+ if (key.startsWith("@_")) continue;
345
+ if (localName(key) === name) {
346
+ const value = node[key];
347
+ return Array.isArray(value) ? unsafeOoxmlBoundaryAssertion(value[0]) : unsafeOoxmlBoundaryAssertion(value);
348
+ }
349
+ }
350
+ return void 0;
351
+ }
352
+ function hasChild(node, name) {
353
+ if (!node) return false;
354
+ for (const key of Object.keys(node)) {
355
+ if (key.startsWith("@_")) continue;
356
+ if (localName(key) === name) return true;
357
+ }
358
+ return false;
359
+ }
360
+ function getChildArray(node, name) {
361
+ if (!node) return [];
362
+ for (const key of Object.keys(node)) {
363
+ if (key.startsWith("@_")) continue;
364
+ if (localName(key) === name) {
365
+ const value = node[key];
366
+ if (value === void 0 || value === null) return [];
367
+ return unsafeOoxmlBoundaryAssertion(Array.isArray(value) ? value : [value]);
368
+ }
369
+ }
370
+ return [];
371
+ }
372
+ function getAttr(node, name) {
373
+ if (!node) return void 0;
374
+ return scalarToString(node[`@_${name}`]);
375
+ }
376
+ function getNamespacedAttr(node, localAttr) {
377
+ if (!node) return void 0;
378
+ for (const key of Object.keys(node)) {
379
+ if (!key.startsWith("@_")) continue;
380
+ const attr = key.slice(2);
381
+ const colon = attr.indexOf(":");
382
+ if (colon !== -1 && attr.slice(colon + 1) === localAttr) {
383
+ const value = scalarToString(node[key]);
384
+ if (value !== void 0) return value;
385
+ }
386
+ }
387
+ return void 0;
388
+ }
389
+ function getChildText(node, name) {
390
+ if (!node) return void 0;
391
+ for (const key of Object.keys(node)) {
392
+ if (key.startsWith("@_")) continue;
393
+ if (localName(key) !== name) continue;
394
+ const value = node[key];
395
+ const item = Array.isArray(value) ? value[0] : value;
396
+ if (typeof item === "string") return item;
397
+ if (typeof item === "number" || typeof item === "boolean") return String(item);
398
+ if (item && typeof item === "object") {
399
+ return scalarToString(unsafeOoxmlBoundaryAssertion(item)["#text"]);
400
+ }
401
+ return void 0;
402
+ }
403
+ return void 0;
404
+ }
405
+ function getAttrs(node) {
406
+ const result = {};
407
+ if (!node) return result;
408
+ for (const key of Object.keys(node)) {
409
+ if (!key.startsWith("@_")) continue;
410
+ const value = scalarToString(node[key]);
411
+ if (value !== void 0) result[key.slice(2)] = value;
412
+ }
413
+ return result;
414
+ }
415
+ function scalarToString(value) {
416
+ if (typeof value === "string") return value;
417
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
418
+ return void 0;
419
+ }
420
+
421
+ // src/reader/raw-node.ts
422
+ var ATTR_PREFIX = "@_";
423
+ var TEXT_KEY = "#text";
424
+ function createSidecarIdFactory(partPath) {
425
+ let counter = 0;
426
+ return () => asRawSidecarId(`${partPath}#raw-${counter++}`);
427
+ }
428
+ function xmlValueToRawNode(name, value) {
429
+ if (typeof value !== "object" || value === null) {
430
+ const text2 = scalarText(value);
431
+ return text2 !== void 0 && text2 !== "" ? { name, text: text2 } : { name };
432
+ }
433
+ const obj = unsafeOoxmlBoundaryAssertion(value);
434
+ const attributes = {};
435
+ const children = [];
436
+ let text;
437
+ for (const key of Object.keys(obj)) {
438
+ if (key === TEXT_KEY) {
439
+ text = scalarText(obj[key]);
440
+ continue;
441
+ }
442
+ if (key.startsWith(ATTR_PREFIX)) {
443
+ const attrValue = scalarText(obj[key]);
444
+ if (attrValue !== void 0) attributes[key.slice(ATTR_PREFIX.length)] = attrValue;
445
+ continue;
446
+ }
447
+ const childValue = obj[key];
448
+ const items = Array.isArray(childValue) ? childValue : [childValue];
449
+ for (const item of items) {
450
+ children.push(xmlValueToRawNode(key, item));
451
+ }
452
+ }
453
+ return {
454
+ name,
455
+ ...Object.keys(attributes).length > 0 ? { attributes } : {},
456
+ ...children.length > 0 ? { children } : {},
457
+ ...text !== void 0 && text !== "" ? { text } : {}
458
+ };
459
+ }
460
+ function makeSidecar(name, value, nextId, orderingSlot) {
461
+ return {
462
+ id: nextId(),
463
+ node: xmlValueToRawNode(name, value),
464
+ ...orderingSlot !== void 0 ? { orderingSlot } : {}
465
+ };
466
+ }
467
+ function collectUnknownSidecars(parent, knownLocalNames, nextId) {
468
+ if (!parent) return [];
469
+ const sidecars = [];
470
+ let slot = 0;
471
+ for (const key of Object.keys(parent)) {
472
+ if (key.startsWith(ATTR_PREFIX) || key === TEXT_KEY) continue;
473
+ const value = parent[key];
474
+ const items = Array.isArray(value) ? value : [value];
475
+ if (knownLocalNames.has(localName(key))) {
476
+ slot += items.length;
477
+ continue;
478
+ }
479
+ for (const item of items) {
480
+ sidecars.push(makeSidecar(key, item, nextId, slot));
481
+ slot++;
482
+ }
483
+ }
484
+ return sidecars;
485
+ }
486
+ function scalarText(value) {
487
+ if (typeof value === "string") return value;
488
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
489
+ return void 0;
490
+ }
491
+
492
+ // src/reader/drawing.ts
493
+ var RECTANGLE_ALIGNMENT_TOKENS = /* @__PURE__ */ new Set([
494
+ "tl",
495
+ "t",
496
+ "tr",
497
+ "l",
498
+ "ctr",
499
+ "r",
500
+ "bl",
501
+ "b",
502
+ "br"
503
+ ]);
504
+ var COLOR_TRANSFORM_KINDS = /* @__PURE__ */ new Set([
505
+ "lumMod",
506
+ "lumOff",
507
+ "tint",
508
+ "shade",
509
+ "alpha"
510
+ ]);
511
+ var RAW_FILL_LOCAL_NAMES = ["grpFill"];
512
+ var PRESET_COLOR_HEX = {
513
+ black: "000000",
514
+ white: "FFFFFF",
515
+ red: "FF0000",
516
+ green: "008000",
517
+ blue: "0000FF",
518
+ yellow: "FFFF00",
519
+ cyan: "00FFFF",
520
+ magenta: "FF00FF"
521
+ };
522
+ function parseColorElement(parent) {
523
+ if (!parent) return void 0;
524
+ const srgb = getChild(parent, "srgbClr");
525
+ if (srgb) {
526
+ const hex = getAttr(srgb, "val");
527
+ if (hex !== void 0) {
528
+ return withTransforms({ kind: "srgb", hex: hex.toUpperCase() }, srgb);
529
+ }
530
+ }
531
+ const scheme = getChild(parent, "schemeClr");
532
+ if (scheme) {
533
+ const name = getAttr(scheme, "val");
534
+ if (name !== void 0) {
535
+ return withTransforms({ kind: "scheme", scheme: name }, scheme);
536
+ }
537
+ }
538
+ const sys = getChild(parent, "sysClr");
539
+ if (sys) {
540
+ const val = getAttr(sys, "val");
541
+ if (val !== void 0) {
542
+ const lastClr = getAttr(sys, "lastClr");
543
+ return withTransforms(
544
+ {
545
+ kind: "system",
546
+ value: val,
547
+ ...lastClr !== void 0 ? { lastColor: lastClr.toUpperCase() } : {}
548
+ },
549
+ sys
550
+ );
551
+ }
552
+ }
553
+ return void 0;
554
+ }
555
+ function parseEffectList(effectList) {
556
+ if (effectList === void 0) return void 0;
557
+ const outerShadow = parseOuterShadow(getChild(effectList, "outerShdw"));
558
+ const innerShadow = parseInnerShadow(getChild(effectList, "innerShdw"));
559
+ const glow = parseGlow(getChild(effectList, "glow"));
560
+ const softEdge = parseSoftEdge(getChild(effectList, "softEdge"));
561
+ const parsed = {
562
+ ...outerShadow !== void 0 ? { outerShadow } : {},
563
+ ...innerShadow !== void 0 ? { innerShadow } : {},
564
+ ...glow !== void 0 ? { glow } : {},
565
+ ...softEdge !== void 0 ? { softEdge } : {}
566
+ };
567
+ return Object.keys(parsed).length > 0 ? parsed : void 0;
568
+ }
569
+ function parseBlipEffects(blip) {
570
+ if (blip === void 0) return void 0;
571
+ const grayscale = getChild(blip, "grayscl") !== void 0;
572
+ const biLevel = parseBiLevel(getChild(blip, "biLevel"));
573
+ const blur = parseBlurEffect(getChild(blip, "blur"));
574
+ const lum = parseLumEffect(getChild(blip, "lum"));
575
+ const duotone = parseDuotoneEffect(getChild(blip, "duotone"));
576
+ const clrChange = parseColorChangeEffect(getChild(blip, "clrChange"));
577
+ const parsed = {
578
+ grayscale,
579
+ ...biLevel !== void 0 ? { biLevel } : {},
580
+ ...blur !== void 0 ? { blur } : {},
581
+ ...lum !== void 0 ? { lum } : {},
582
+ ...duotone !== void 0 ? { duotone } : {},
583
+ ...clrChange !== void 0 ? { clrChange } : {}
584
+ };
585
+ return grayscale || biLevel !== void 0 || blur !== void 0 || lum !== void 0 || duotone !== void 0 || clrChange !== void 0 ? parsed : void 0;
586
+ }
587
+ function parseOuterShadow(node) {
588
+ if (node === void 0) return void 0;
589
+ const color = parseColorElement(node);
590
+ if (color === void 0) return void 0;
591
+ return {
592
+ blurRadius: asEmu(numericAttr(node, "blurRad") ?? 0),
593
+ distance: asEmu(numericAttr(node, "dist") ?? 0),
594
+ direction: asOoxmlAngle(numericAttr(node, "dir") ?? 0),
595
+ color,
596
+ alignment: parseRectangleAlignment(getAttr(node, "algn"), "b"),
597
+ rotateWithShape: getAttr(node, "rotWithShape") !== "0"
598
+ };
599
+ }
600
+ function parseInnerShadow(node) {
601
+ if (node === void 0) return void 0;
602
+ const color = parseColorElement(node);
603
+ if (color === void 0) return void 0;
604
+ return {
605
+ blurRadius: asEmu(numericAttr(node, "blurRad") ?? 0),
606
+ distance: asEmu(numericAttr(node, "dist") ?? 0),
607
+ direction: asOoxmlAngle(numericAttr(node, "dir") ?? 0),
608
+ color
609
+ };
610
+ }
611
+ function parseGlow(node) {
612
+ if (node === void 0) return void 0;
613
+ const color = parseColorElement(node);
614
+ if (color === void 0) return void 0;
615
+ return {
616
+ radius: asEmu(numericAttr(node, "rad") ?? 0),
617
+ color
618
+ };
619
+ }
620
+ function parseSoftEdge(node) {
621
+ if (node === void 0) return void 0;
622
+ return {
623
+ radius: asEmu(numericAttr(node, "rad") ?? 0)
624
+ };
625
+ }
626
+ function parseBiLevel(node) {
627
+ if (node === void 0) return void 0;
628
+ return {
629
+ threshold: (numericAttr(node, "thresh") ?? 5e4) / 1e5
630
+ };
631
+ }
632
+ function parseBlurEffect(node) {
633
+ if (node === void 0) return void 0;
634
+ return {
635
+ radius: asEmu(numericAttr(node, "rad") ?? 0),
636
+ grow: getAttr(node, "grow") !== "0"
637
+ };
638
+ }
639
+ function parseLumEffect(node) {
640
+ if (node === void 0) return void 0;
641
+ return {
642
+ brightness: (numericAttr(node, "bright") ?? 0) / 1e5,
643
+ contrast: (numericAttr(node, "contrast") ?? 0) / 1e5
644
+ };
645
+ }
646
+ function parseDuotoneEffect(node) {
647
+ if (node === void 0) return void 0;
648
+ const colors = collectColorChildren(node);
649
+ if (colors.length < 2) return void 0;
650
+ return { color1: colors[0], color2: colors[1] };
651
+ }
652
+ function parseColorChangeEffect(node) {
653
+ if (node === void 0) return void 0;
654
+ const from = firstColorChild(getChild(node, "clrFrom"));
655
+ const to = firstColorChild(getChild(node, "clrTo"));
656
+ return from !== void 0 && to !== void 0 ? { from, to } : void 0;
657
+ }
658
+ function collectColorChildren(parent) {
659
+ const colors = [];
660
+ for (const [key, value] of Object.entries(parent)) {
661
+ if (key.startsWith("@_")) continue;
662
+ const nodes = Array.isArray(value) ? value : [value];
663
+ for (const node of nodes) {
664
+ if (!isXmlNode(node)) continue;
665
+ const color = parseColorChild(key, node);
666
+ if (color !== void 0) colors.push(color);
667
+ }
668
+ }
669
+ return colors;
670
+ }
671
+ function firstColorChild(parent) {
672
+ return parent !== void 0 ? collectColorChildren(parent)[0] : void 0;
673
+ }
674
+ function parseColorChild(key, node) {
675
+ const name = localName(key);
676
+ return name === "prstClr" ? parsePresetColor(node) : parseColorElement({ [name]: node });
677
+ }
678
+ function isXmlNode(value) {
679
+ return typeof value === "object" && value !== null;
680
+ }
681
+ function parsePresetColor(node) {
682
+ const value = getAttr(node, "val");
683
+ const hex = value !== void 0 ? PRESET_COLOR_HEX[value] : void 0;
684
+ return hex !== void 0 ? withTransforms({ kind: "srgb", hex }, node) : void 0;
685
+ }
686
+ function parseFill(parent, nextId) {
687
+ if (!parent) return void 0;
688
+ const solid = getChild(parent, "solidFill");
689
+ if (solid) {
690
+ const color = parseColorElement(solid);
691
+ if (color) return { kind: "solid", color };
692
+ return { kind: "raw", raw: makeSidecar("a:solidFill", solid, nextId) };
693
+ }
694
+ if (hasChild(parent, "noFill")) return { kind: "none" };
695
+ const grad = getChild(parent, "gradFill");
696
+ if (grad) {
697
+ const fill = parseGradientFill(grad);
698
+ return fill ?? { kind: "raw", raw: makeSidecar("a:gradFill", grad, nextId) };
699
+ }
700
+ const blip = getChild(parent, "blipFill");
701
+ if (blip) {
702
+ return parseBlipFill(blip) ?? { kind: "raw", raw: makeSidecar("a:blipFill", blip, nextId) };
703
+ }
704
+ const pattern = getChild(parent, "pattFill");
705
+ if (pattern) {
706
+ const fill = parsePatternFill(pattern);
707
+ return fill ?? { kind: "raw", raw: makeSidecar("a:pattFill", pattern, nextId) };
708
+ }
709
+ for (const name of RAW_FILL_LOCAL_NAMES) {
710
+ if (hasChild(parent, name)) {
711
+ return { kind: "raw", raw: makeSidecar(`a:${name}`, getChild(parent, name) ?? {}, nextId) };
712
+ }
713
+ }
714
+ return void 0;
715
+ }
716
+ function parseGradientFill(grad) {
717
+ const stops = [];
718
+ for (const gs of getChildArray(getChild(grad, "gsLst"), "gs")) {
719
+ const color = parseColorElement(gs);
720
+ if (color === void 0) continue;
721
+ stops.push({
722
+ position: (numericAttr(gs, "pos") ?? 0) / 1e5,
723
+ color
724
+ });
725
+ }
726
+ if (stops.length === 0) return void 0;
727
+ const path = getChild(grad, "path");
728
+ if (path !== void 0) {
729
+ const fillToRect = getChild(path, "fillToRect");
730
+ const l = numericAttr(fillToRect, "l") ?? 0;
731
+ const t = numericAttr(fillToRect, "t") ?? 0;
732
+ const r = numericAttr(fillToRect, "r") ?? 0;
733
+ const b = numericAttr(fillToRect, "b") ?? 0;
734
+ return {
735
+ kind: "gradient",
736
+ gradientType: "radial",
737
+ stops,
738
+ centerX: (l + (1e5 - r)) / 2 / 1e5,
739
+ centerY: (t + (1e5 - b)) / 2 / 1e5
740
+ };
741
+ }
742
+ return {
743
+ kind: "gradient",
744
+ gradientType: "linear",
745
+ stops,
746
+ angle: asOoxmlAngle(numericAttr(getChild(grad, "lin"), "ang") ?? 0)
747
+ };
748
+ }
749
+ function parseBlipFill(blipFill) {
750
+ const blip = getChild(blipFill, "blip");
751
+ const embed = getNamespacedAttr(blip, "embed");
752
+ if (embed === void 0) return void 0;
753
+ const tile = parseImageFillTile(getChild(blipFill, "tile"));
754
+ return {
755
+ kind: "image",
756
+ blipRelationshipId: asRelationshipId(embed),
757
+ ...tile !== void 0 ? { tile } : {}
758
+ };
759
+ }
760
+ function parseImageFillTile(tile) {
761
+ if (tile === void 0) return void 0;
762
+ const flip = getAttr(tile, "flip") ?? "none";
763
+ return {
764
+ tx: asEmu(numericAttr(tile, "tx") ?? 0),
765
+ ty: asEmu(numericAttr(tile, "ty") ?? 0),
766
+ sx: (numericAttr(tile, "sx") ?? 1e5) / 1e5,
767
+ sy: (numericAttr(tile, "sy") ?? 1e5) / 1e5,
768
+ flip: flip === "x" || flip === "y" || flip === "xy" ? flip : "none",
769
+ align: parseRectangleAlignment(getAttr(tile, "algn"), "tl")
770
+ };
771
+ }
772
+ function parseRectangleAlignment(value, fallback) {
773
+ return parseEnumValueWithDefault(value, RECTANGLE_ALIGNMENT_TOKENS, fallback);
774
+ }
775
+ function parsePatternFill(pattern) {
776
+ const foregroundColor = parseColorElement(getChild(pattern, "fgClr"));
777
+ const backgroundColor = parseColorElement(getChild(pattern, "bgClr"));
778
+ if (foregroundColor === void 0 || backgroundColor === void 0) return void 0;
779
+ return {
780
+ kind: "pattern",
781
+ preset: getAttr(pattern, "prst") ?? "ltDnDiag",
782
+ foregroundColor,
783
+ backgroundColor
784
+ };
785
+ }
786
+ function parseOutline(spPr, nextId) {
787
+ const ln = getChild(spPr, "ln");
788
+ return parseLine(ln, nextId);
789
+ }
790
+ function parseLine(ln, nextId) {
791
+ if (!ln) return void 0;
792
+ const width = numericAttr(ln, "w");
793
+ const fill = parseFill(ln, nextId);
794
+ const dashStyle = parseDashStyle(getChild(ln, "prstDash"));
795
+ const customDash = parseCustomDash(ln);
796
+ const lineCap = parseLineCap(getAttr(ln, "cap"));
797
+ const lineJoin = parseLineJoin(ln);
798
+ const headEnd = parseArrowEndpoint(getChild(ln, "headEnd"));
799
+ const tailEnd = parseArrowEndpoint(getChild(ln, "tailEnd"));
800
+ return {
801
+ ...width !== void 0 ? { width: asEmu(width) } : {},
802
+ ...fill !== void 0 ? { fill } : {},
803
+ ...dashStyle !== void 0 ? { dashStyle } : {},
804
+ ...customDash !== void 0 ? { customDash } : {},
805
+ ...lineCap !== void 0 ? { lineCap } : {},
806
+ ...lineJoin !== void 0 ? { lineJoin } : {},
807
+ ...headEnd !== void 0 ? { headEnd } : {},
808
+ ...tailEnd !== void 0 ? { tailEnd } : {}
809
+ };
810
+ }
811
+ function parseTransform(spPr) {
812
+ const xfrm = getChild(spPr, "xfrm");
813
+ if (!xfrm) return void 0;
814
+ const off = getChild(xfrm, "off");
815
+ const ext = getChild(xfrm, "ext");
816
+ const offsetX = numericAttr(off, "x");
817
+ const offsetY = numericAttr(off, "y");
818
+ const width = numericAttr(ext, "cx");
819
+ const height = numericAttr(ext, "cy");
820
+ if (offsetX === void 0 || offsetY === void 0 || width === void 0 || height === void 0) {
821
+ return void 0;
822
+ }
823
+ const rotation = numericAttr(xfrm, "rot");
824
+ const flipH = getAttr(xfrm, "flipH");
825
+ const flipV = getAttr(xfrm, "flipV");
826
+ return {
827
+ offsetX: asEmu(offsetX),
828
+ offsetY: asEmu(offsetY),
829
+ width: asEmu(width),
830
+ height: asEmu(height),
831
+ ...rotation !== void 0 ? { rotation: asOoxmlAngle(rotation) } : {},
832
+ ...isTrue(flipH) ? { flipHorizontal: true } : {},
833
+ ...isTrue(flipV) ? { flipVertical: true } : {}
834
+ };
835
+ }
836
+ function withTransforms(base, colorNode) {
837
+ const transforms = [];
838
+ for (const key of Object.keys(colorNode)) {
839
+ if (key.startsWith("@_")) continue;
840
+ const kind = localName(key);
841
+ const transformKind = parseEnumValue(kind, COLOR_TRANSFORM_KINDS);
842
+ if (transformKind === void 0) continue;
843
+ const value = colorNode[key];
844
+ const items = Array.isArray(value) ? value : [value];
845
+ for (const item of items) {
846
+ const raw = getAttr(unsafeOoxmlBoundaryAssertion(item), "val");
847
+ if (raw === void 0) continue;
848
+ const numeric = Number(raw);
849
+ if (!Number.isFinite(numeric)) continue;
850
+ transforms.push({
851
+ kind: transformKind,
852
+ value: asOoxmlPercent(numeric)
853
+ });
854
+ }
855
+ }
856
+ return transforms.length > 0 ? { ...base, transforms } : base;
857
+ }
858
+ function numericAttr(node, name) {
859
+ const raw = getAttr(node, name);
860
+ if (raw === void 0) return void 0;
861
+ const value = Number(raw);
862
+ return Number.isFinite(value) ? value : void 0;
863
+ }
864
+ function isTrue(value) {
865
+ return value === "1" || value === "true";
866
+ }
867
+ function parseDashStyle(prstDash) {
868
+ const value = getAttr(prstDash, "val");
869
+ return parseEnumValue(value, DASH_STYLES);
870
+ }
871
+ function parseCustomDash(ln) {
872
+ const custDash = getChild(ln, "custDash");
873
+ const segments = getChildArray(custDash, "ds");
874
+ if (segments.length === 0) return void 0;
875
+ return segments.flatMap((segment) => [
876
+ (numericAttr(segment, "d") ?? 1e5) / 1e5,
877
+ (numericAttr(segment, "sp") ?? 1e5) / 1e5
878
+ ]);
879
+ }
880
+ var LINE_CAP_MAP = {
881
+ flat: "butt",
882
+ sq: "square",
883
+ rnd: "round"
884
+ };
885
+ function parseLineCap(value) {
886
+ return value !== void 0 ? LINE_CAP_MAP[value] : void 0;
887
+ }
888
+ function parseLineJoin(ln) {
889
+ if (hasChild(ln, "round")) return "round";
890
+ if (hasChild(ln, "bevel")) return "bevel";
891
+ if (hasChild(ln, "miter")) return "miter";
892
+ return void 0;
893
+ }
894
+ function parseArrowEndpoint(node) {
895
+ if (!node) return void 0;
896
+ const type = parseEnumValue(getAttr(node, "type"), ARROW_TYPES);
897
+ if (type === void 0) return void 0;
898
+ const width = getAttr(node, "w") ?? "med";
899
+ const length = getAttr(node, "len") ?? "med";
900
+ return {
901
+ type,
902
+ width: parseEnumValueWithDefault(width, ARROW_SIZES, "med"),
903
+ length: parseEnumValueWithDefault(length, ARROW_SIZES, "med")
904
+ };
905
+ }
906
+ var DASH_STYLES = /* @__PURE__ */ new Set([
907
+ "solid",
908
+ "dash",
909
+ "dot",
910
+ "dashDot",
911
+ "lgDash",
912
+ "lgDashDot",
913
+ "sysDash",
914
+ "sysDot"
915
+ ]);
916
+ var ARROW_TYPES = /* @__PURE__ */ new Set([
917
+ "triangle",
918
+ "stealth",
919
+ "diamond",
920
+ "oval",
921
+ "arrow"
922
+ ]);
923
+ var ARROW_SIZES = /* @__PURE__ */ new Set(["sm", "med", "lg"]);
924
+
925
+ // src/reader/custom-geometry.ts
926
+ function parseCustomGeometry(custGeom, orderedCustGeom) {
927
+ const pathLst = getChild(custGeom, "pathLst");
928
+ const paths = getChildArray(pathLst, "path");
929
+ if (paths.length === 0) return void 0;
930
+ const avGuides = parseGuideList(getChild(custGeom, "avLst"));
931
+ const guides = parseGuideList(getChild(custGeom, "gdLst"));
932
+ const orderedPaths = orderedChildEntries(
933
+ orderedChildChildren(orderedCustGeom, "pathLst"),
934
+ "path"
935
+ );
936
+ const result = [];
937
+ for (const [index, path] of paths.entries()) {
938
+ const width = numericAttr2(path, "w") ?? 0;
939
+ const height = numericAttr2(path, "h") ?? 0;
940
+ if (width === 0 && height === 0) continue;
941
+ const variables = evaluateGuides(avGuides, guides, width, height);
942
+ const commands = buildPathCommands(path, variables, orderedNodeChildren(orderedPaths[index]));
943
+ if (commands !== void 0) result.push({ width, height, commands });
944
+ }
945
+ return result.length > 0 ? result : void 0;
946
+ }
947
+ function parseGuideList(parent) {
948
+ return getChildArray(parent, "gd").map((guide) => ({
949
+ name: getAttr(guide, "name") ?? "",
950
+ formula: getAttr(guide, "fmla") ?? ""
951
+ })).filter((guide) => guide.name !== "" && guide.formula !== "");
952
+ }
953
+ function buildPathCommands(path, variables, orderedCommands) {
954
+ const parts = [];
955
+ let currentX = 0;
956
+ let currentY = 0;
957
+ let startX = 0;
958
+ let startY = 0;
959
+ for (const { local, nodes } of pathCommandNodes(path, orderedCommands)) {
960
+ for (const node of nodes) {
961
+ if (local === "moveTo") {
962
+ const point = firstPoint(node, variables);
963
+ if (point !== void 0) {
964
+ parts.push(`M ${point.x} ${point.y}`);
965
+ currentX = point.x;
966
+ currentY = point.y;
967
+ startX = point.x;
968
+ startY = point.y;
969
+ }
970
+ } else if (local === "lnTo") {
971
+ const point = firstPoint(node, variables);
972
+ if (point !== void 0) {
973
+ parts.push(`L ${point.x} ${point.y}`);
974
+ currentX = point.x;
975
+ currentY = point.y;
976
+ }
977
+ } else if (local === "cubicBezTo") {
978
+ const points = allPoints(node, variables);
979
+ if (points.length >= 3) {
980
+ parts.push(`C ${points.map((point) => `${point.x} ${point.y}`).join(", ")}`);
981
+ currentX = points[points.length - 1].x;
982
+ currentY = points[points.length - 1].y;
983
+ }
984
+ } else if (local === "quadBezTo") {
985
+ const points = allPoints(node, variables);
986
+ if (points.length >= 2) {
987
+ parts.push(`Q ${points.map((point) => `${point.x} ${point.y}`).join(", ")}`);
988
+ currentX = points[points.length - 1].x;
989
+ currentY = points[points.length - 1].y;
990
+ }
991
+ } else if (local === "arcTo") {
992
+ const arc = convertArcTo(node, currentX, currentY, variables);
993
+ if (arc !== void 0) {
994
+ parts.push(arc.command);
995
+ currentX = arc.endX;
996
+ currentY = arc.endY;
997
+ }
998
+ } else if (local === "close") {
999
+ parts.push("Z");
1000
+ currentX = startX;
1001
+ currentY = startY;
1002
+ }
1003
+ }
1004
+ }
1005
+ return parts.length > 0 ? parts.join(" ") : void 0;
1006
+ }
1007
+ function pathCommandNodes(path, orderedCommands) {
1008
+ if (orderedCommands === void 0) {
1009
+ return Object.keys(path).filter((key) => !key.startsWith("@_")).map((key) => ({ local: localName(key), nodes: getChildArray(path, localName(key)) }));
1010
+ }
1011
+ const counters = {};
1012
+ const result = [];
1013
+ for (const command of orderedCommands) {
1014
+ const key = orderedNodeKey(command);
1015
+ if (key === void 0) continue;
1016
+ const local = localName(key);
1017
+ const index = counters[local] ?? 0;
1018
+ counters[local] = index + 1;
1019
+ const node = getChildArray(path, local)[index];
1020
+ if (node !== void 0) result.push({ local, nodes: [node] });
1021
+ }
1022
+ return result;
1023
+ }
1024
+ function firstPoint(node, variables) {
1025
+ return allPoints(node, variables)[0];
1026
+ }
1027
+ function allPoints(node, variables) {
1028
+ return getChildArray(node, "pt").map((point) => ({
1029
+ x: resolveValue(getAttr(point, "x") ?? "0", variables),
1030
+ y: resolveValue(getAttr(point, "y") ?? "0", variables)
1031
+ }));
1032
+ }
1033
+ function convertArcTo(arc, currentX, currentY, variables) {
1034
+ const widthRadius = resolveValue(getAttr(arc, "wR") ?? "0", variables);
1035
+ const heightRadius = resolveValue(getAttr(arc, "hR") ?? "0", variables);
1036
+ const startAngle = resolveValue(getAttr(arc, "stAng") ?? "0", variables);
1037
+ const sweepAngle = resolveValue(getAttr(arc, "swAng") ?? "0", variables);
1038
+ if (widthRadius === 0 && heightRadius === 0 || sweepAngle === 0) return void 0;
1039
+ const startRadians = startAngle / 6e4 * (Math.PI / 180);
1040
+ const endRadians = (startAngle + sweepAngle) / 6e4 * (Math.PI / 180);
1041
+ const centerX = currentX - widthRadius * Math.cos(startRadians);
1042
+ const centerY = currentY - heightRadius * Math.sin(startRadians);
1043
+ const endX = centerX + widthRadius * Math.cos(endRadians);
1044
+ const endY = centerY + heightRadius * Math.sin(endRadians);
1045
+ const largeArcFlag = Math.abs(sweepAngle / 6e4) > 180 ? 1 : 0;
1046
+ const sweepFlag = sweepAngle > 0 ? 1 : 0;
1047
+ return {
1048
+ command: `A ${round(widthRadius)} ${round(heightRadius)} 0 ${largeArcFlag} ${sweepFlag} ${round(endX)} ${round(endY)}`,
1049
+ endX,
1050
+ endY
1051
+ };
1052
+ }
1053
+ function evaluateGuides(avGuides, guides, width, height) {
1054
+ const variables = createBuiltinVariables(width, height);
1055
+ for (const guide of avGuides) variables[guide.name] = evaluateFormula(guide.formula, variables);
1056
+ for (const guide of guides) variables[guide.name] = evaluateFormula(guide.formula, variables);
1057
+ return variables;
1058
+ }
1059
+ function createBuiltinVariables(width, height) {
1060
+ return {
1061
+ w: width,
1062
+ h: height,
1063
+ l: 0,
1064
+ t: 0,
1065
+ r: width,
1066
+ b: height,
1067
+ wd2: width / 2,
1068
+ hd2: height / 2,
1069
+ wd4: width / 4,
1070
+ hd4: height / 4,
1071
+ ss: Math.min(width, height),
1072
+ ls: Math.max(width, height),
1073
+ cd2: 108e5,
1074
+ cd4: 54e5,
1075
+ cd8: 27e5,
1076
+ "3cd4": 162e5
1077
+ };
1078
+ }
1079
+ function evaluateFormula(formula, variables) {
1080
+ const tokens = formula.trim().split(/\s+/);
1081
+ const op = tokens[0];
1082
+ const resolve = (token) => {
1083
+ if (token === void 0) return 0;
1084
+ const value = Number(token);
1085
+ return Number.isNaN(value) ? variables[token] ?? 0 : value;
1086
+ };
1087
+ if (op === "val") return resolve(tokens[1]);
1088
+ if (op === "+-") return resolve(tokens[1]) + resolve(tokens[2]) - resolve(tokens[3]);
1089
+ if (op === "*/")
1090
+ return Math.round(resolve(tokens[1]) * resolve(tokens[2]) / (resolve(tokens[3]) || 1));
1091
+ if (op === "+/")
1092
+ return Math.round((resolve(tokens[1]) + resolve(tokens[2])) / (resolve(tokens[3]) || 1));
1093
+ if (op === "pin")
1094
+ return Math.max(resolve(tokens[1]), Math.min(resolve(tokens[2]), resolve(tokens[3])));
1095
+ if (op === "min") return Math.min(resolve(tokens[1]), resolve(tokens[2]));
1096
+ if (op === "max") return Math.max(resolve(tokens[1]), resolve(tokens[2]));
1097
+ if (op === "abs") return Math.abs(resolve(tokens[1]));
1098
+ if (op === "sqrt") return Math.round(Math.sqrt(resolve(tokens[1])));
1099
+ if (op === "sin") return Math.round(resolve(tokens[1]) * Math.sin(toRadians(resolve(tokens[2]))));
1100
+ if (op === "cos") return Math.round(resolve(tokens[1]) * Math.cos(toRadians(resolve(tokens[2]))));
1101
+ if (op === "tan") return Math.round(resolve(tokens[1]) * Math.tan(toRadians(resolve(tokens[2]))));
1102
+ if (op === "at2")
1103
+ return Math.round(Math.atan2(resolve(tokens[2]), resolve(tokens[1])) * (180 / Math.PI) * 6e4);
1104
+ if (op === "mod") {
1105
+ const a = resolve(tokens[1]);
1106
+ const b = resolve(tokens[2]);
1107
+ const c = resolve(tokens[3]);
1108
+ return Math.round(Math.sqrt(a * a + b * b + c * c));
1109
+ }
1110
+ if (op === "cat2") {
1111
+ return Math.round(
1112
+ resolve(tokens[1]) * Math.cos(Math.atan2(resolve(tokens[3]), resolve(tokens[2])))
1113
+ );
1114
+ }
1115
+ if (op === "sat2") {
1116
+ return Math.round(
1117
+ resolve(tokens[1]) * Math.sin(Math.atan2(resolve(tokens[3]), resolve(tokens[2])))
1118
+ );
1119
+ }
1120
+ if (op === "?:") return resolve(tokens[1]) > 0 ? resolve(tokens[2]) : resolve(tokens[3]);
1121
+ return 0;
1122
+ }
1123
+ function resolveValue(value, variables) {
1124
+ const numeric = Number(value);
1125
+ return Number.isNaN(numeric) ? variables[value] ?? 0 : numeric;
1126
+ }
1127
+ function numericAttr2(node, name) {
1128
+ const raw = getAttr(node, name);
1129
+ if (raw === void 0) return void 0;
1130
+ const value = Number(raw);
1131
+ return Number.isFinite(value) ? value : void 0;
1132
+ }
1133
+ function round(value) {
1134
+ return Math.round(value * 1e3) / 1e3;
1135
+ }
1136
+ function toRadians(ooxmlAngle) {
1137
+ return ooxmlAngle / 6e4 * (Math.PI / 180);
1138
+ }
1139
+ function orderedChildChildren(parent, childLocalName) {
1140
+ const child = orderedChildEntries(parent, childLocalName)[0];
1141
+ return orderedNodeChildren(child);
1142
+ }
1143
+ function orderedChildEntries(parent, childLocalName) {
1144
+ if (parent === void 0) return [];
1145
+ return parent.filter((child) => {
1146
+ const key = orderedNodeKey(child);
1147
+ return key !== void 0 && localName(key) === childLocalName;
1148
+ });
1149
+ }
1150
+ function orderedNodeChildren(node) {
1151
+ const key = node !== void 0 ? orderedNodeKey(node) : void 0;
1152
+ const value = key !== void 0 ? node?.[key] : void 0;
1153
+ return Array.isArray(value) ? value : void 0;
1154
+ }
1155
+ function orderedNodeKey(node) {
1156
+ return Object.keys(node).find((key) => key !== ":@");
1157
+ }
1158
+
1159
+ // src/reader/text.ts
1160
+ var KNOWN_TXBODY_CHILDREN = /* @__PURE__ */ new Set(["bodyPr", "lstStyle", "p"]);
1161
+ var KNOWN_PARAGRAPH_CHILDREN = /* @__PURE__ */ new Set([
1162
+ "pPr",
1163
+ "r",
1164
+ "fld",
1165
+ "br",
1166
+ "endParaRPr"
1167
+ ]);
1168
+ var KNOWN_RUN_CHILDREN = /* @__PURE__ */ new Set(["rPr", "t"]);
1169
+ var KNOWN_RUN_PROPERTY_CHILDREN = /* @__PURE__ */ new Set([
1170
+ "latin",
1171
+ "ea",
1172
+ "cs",
1173
+ "solidFill"
1174
+ ]);
1175
+ var ALIGN_MAP = {
1176
+ l: "left",
1177
+ ctr: "center",
1178
+ r: "right",
1179
+ just: "justify"
1180
+ };
1181
+ var ANCHOR_MAP = {
1182
+ t: "top",
1183
+ ctr: "middle",
1184
+ b: "bottom"
1185
+ };
1186
+ var WRAP_VALUES = /* @__PURE__ */ new Set(["square", "none"]);
1187
+ var VERTICAL_VALUES = /* @__PURE__ */ new Set([
1188
+ "horz",
1189
+ "vert",
1190
+ "vert270",
1191
+ "eaVert",
1192
+ "wordArtVert",
1193
+ "mongolianVert"
1194
+ ]);
1195
+ var VALID_AUTO_NUM_SCHEMES = /* @__PURE__ */ new Set([
1196
+ "arabicPeriod",
1197
+ "arabicParenR",
1198
+ "romanUcPeriod",
1199
+ "romanLcPeriod",
1200
+ "alphaUcPeriod",
1201
+ "alphaLcPeriod",
1202
+ "alphaLcParenR",
1203
+ "alphaUcParenR",
1204
+ "arabicPlain"
1205
+ ]);
1206
+ function parseTextBody(txBody, partPath, nextId, ownerNodeId, ownerOrderingSlot, orderedTxBody) {
1207
+ if (!txBody) return void 0;
1208
+ const properties = parseBodyProperties(getChild(txBody, "bodyPr"));
1209
+ const listStyle = parseTextStyle(getChild(txBody, "lstStyle"));
1210
+ const orderedParagraphs = orderedTxBody?.filter((child) => orderedLocalName(child) === "p").map((child) => {
1211
+ const key = orderedKey(child);
1212
+ const value = key !== void 0 ? child[key] : void 0;
1213
+ return Array.isArray(value) ? value : void 0;
1214
+ });
1215
+ const paragraphs = [];
1216
+ let logicalParagraphIndex = 0;
1217
+ getChildArray(txBody, "p").forEach((p, paragraphIndex) => {
1218
+ const orderedChildren = orderedParagraphs?.[paragraphIndex];
1219
+ if (orderedChildren !== void 0 && hasMultipleBulletPPr(p, orderedChildren)) {
1220
+ const split = splitInterleavedParagraph(
1221
+ p,
1222
+ orderedChildren,
1223
+ partPath,
1224
+ nextId,
1225
+ ownerNodeId,
1226
+ ownerOrderingSlot,
1227
+ logicalParagraphIndex
1228
+ );
1229
+ paragraphs.push(...split);
1230
+ logicalParagraphIndex += split.length;
1231
+ return;
1232
+ }
1233
+ paragraphs.push(
1234
+ parseParagraph(
1235
+ p,
1236
+ partPath,
1237
+ nextId,
1238
+ ownerNodeId,
1239
+ ownerOrderingSlot,
1240
+ logicalParagraphIndex,
1241
+ orderedChildren
1242
+ )
1243
+ );
1244
+ logicalParagraphIndex++;
1245
+ });
1246
+ const rawSidecars = collectUnknownSidecars(txBody, KNOWN_TXBODY_CHILDREN, nextId);
1247
+ return {
1248
+ paragraphs,
1249
+ ...properties !== void 0 ? { properties } : {},
1250
+ ...listStyle !== void 0 ? { listStyle } : {},
1251
+ handle: { partPath },
1252
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
1253
+ };
1254
+ }
1255
+ function parseTextStyle(node) {
1256
+ if (node === void 0) return void 0;
1257
+ const defaultParagraph = parseParagraphProperties(getChild(node, "defPPr"));
1258
+ const levels = Array.from(
1259
+ { length: 9 },
1260
+ (_, index) => parseParagraphProperties(getChild(node, `lvl${index + 1}pPr`))
1261
+ );
1262
+ if (defaultParagraph === void 0 && levels.every((level) => level === void 0)) {
1263
+ return void 0;
1264
+ }
1265
+ return { ...defaultParagraph !== void 0 ? { defaultParagraph } : {}, levels };
1266
+ }
1267
+ function hasMultipleBulletPPr(p, orderedChildren) {
1268
+ const pPrList = getChildArray(p, "pPr");
1269
+ let bulletPPrCount = 0;
1270
+ let pPrCounter = 0;
1271
+ for (const child of orderedChildren) {
1272
+ if (orderedLocalName(child) !== "pPr") continue;
1273
+ const pPr = pPrList[pPrCounter];
1274
+ if (pPr !== void 0 && (getChild(pPr, "buChar") !== void 0 || getChild(pPr, "buAutoNum") !== void 0)) {
1275
+ bulletPPrCount++;
1276
+ if (bulletPPrCount >= 2) return true;
1277
+ }
1278
+ pPrCounter++;
1279
+ }
1280
+ return false;
1281
+ }
1282
+ function splitInterleavedParagraph(p, orderedChildren, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex) {
1283
+ const pPrList = getChildArray(p, "pPr");
1284
+ const rList = getChildArray(p, "r");
1285
+ const fldList = getChildArray(p, "fld");
1286
+ const brList = getChildArray(p, "br");
1287
+ const groups = [];
1288
+ let currentGroup;
1289
+ let pPrCounter = 0;
1290
+ let runCounter = 0;
1291
+ let fieldCounter = 0;
1292
+ let breakCounter = 0;
1293
+ for (const child of orderedChildren) {
1294
+ const tag = orderedLocalName(child);
1295
+ if (tag === "pPr") {
1296
+ const pPr = pPrList[pPrCounter];
1297
+ const hasBullet = pPr !== void 0 && (getChild(pPr, "buChar") !== void 0 || getChild(pPr, "buAutoNum") !== void 0);
1298
+ if (hasBullet || currentGroup === void 0) {
1299
+ if (currentGroup !== void 0) groups.push(currentGroup);
1300
+ currentGroup = {
1301
+ pPrIndex: pPrCounter,
1302
+ rNodes: [],
1303
+ fldNodes: [],
1304
+ brNodes: [],
1305
+ orderedChildren: [child]
1306
+ };
1307
+ } else {
1308
+ currentGroup.orderedChildren.push(child);
1309
+ }
1310
+ pPrCounter++;
1311
+ } else if (tag === "r") {
1312
+ currentGroup ??= {
1313
+ pPrIndex: -1,
1314
+ rNodes: [],
1315
+ fldNodes: [],
1316
+ brNodes: [],
1317
+ orderedChildren: []
1318
+ };
1319
+ currentGroup.orderedChildren.push(child);
1320
+ if (rList[runCounter] !== void 0) currentGroup.rNodes.push(rList[runCounter]);
1321
+ runCounter++;
1322
+ } else if (tag === "fld") {
1323
+ currentGroup ??= {
1324
+ pPrIndex: -1,
1325
+ rNodes: [],
1326
+ fldNodes: [],
1327
+ brNodes: [],
1328
+ orderedChildren: []
1329
+ };
1330
+ currentGroup.orderedChildren.push(child);
1331
+ if (fldList[fieldCounter] !== void 0) currentGroup.fldNodes.push(fldList[fieldCounter]);
1332
+ fieldCounter++;
1333
+ } else if (tag === "br") {
1334
+ currentGroup ??= {
1335
+ pPrIndex: -1,
1336
+ rNodes: [],
1337
+ fldNodes: [],
1338
+ brNodes: [],
1339
+ orderedChildren: []
1340
+ };
1341
+ currentGroup.orderedChildren.push(child);
1342
+ if (brList[breakCounter] !== void 0) currentGroup.brNodes.push(brList[breakCounter]);
1343
+ breakCounter++;
1344
+ }
1345
+ }
1346
+ if (currentGroup !== void 0) groups.push(currentGroup);
1347
+ return groups.map((group, groupIndex) => {
1348
+ const synthetic = {};
1349
+ if (group.pPrIndex >= 0) synthetic.pPr = pPrList[group.pPrIndex];
1350
+ synthetic.r = group.rNodes;
1351
+ synthetic.fld = group.fldNodes;
1352
+ synthetic.br = group.brNodes;
1353
+ if (groupIndex === groups.length - 1 && getChild(p, "endParaRPr") !== void 0) {
1354
+ synthetic.endParaRPr = getChild(p, "endParaRPr");
1355
+ }
1356
+ const paragraph = parseParagraph(
1357
+ synthetic,
1358
+ partPath,
1359
+ nextId,
1360
+ ownerNodeId,
1361
+ ownerOrderingSlot,
1362
+ paragraphIndex + groupIndex,
1363
+ group.orderedChildren
1364
+ );
1365
+ if (groupIndex < groups.length - 1 && paragraph.runs.length > 0) {
1366
+ const lastRun = paragraph.runs[paragraph.runs.length - 1];
1367
+ if (lastRun.text.endsWith("\n")) {
1368
+ const trimmed = lastRun.text.slice(0, -1);
1369
+ const precedingRuns = paragraph.runs.slice(0, -1);
1370
+ return {
1371
+ ...paragraph,
1372
+ runs: trimmed === "" ? precedingRuns : [...precedingRuns, { ...lastRun, text: trimmed }]
1373
+ };
1374
+ }
1375
+ }
1376
+ return paragraph;
1377
+ });
1378
+ }
1379
+ function parseBodyProperties(bodyPr) {
1380
+ if (!bodyPr) return void 0;
1381
+ const marginLeft = numericAttr(bodyPr, "lIns");
1382
+ const marginRight = numericAttr(bodyPr, "rIns");
1383
+ const marginTop = numericAttr(bodyPr, "tIns");
1384
+ const marginBottom = numericAttr(bodyPr, "bIns");
1385
+ const anchorToken = getAttr(bodyPr, "anchor");
1386
+ const anchor = anchorToken !== void 0 ? ANCHOR_MAP[anchorToken] : void 0;
1387
+ const wrap = parseWrap(getAttr(bodyPr, "wrap"));
1388
+ const vert = parseVerticalType(getAttr(bodyPr, "vert"));
1389
+ const numCol = numericAttr(bodyPr, "numCol");
1390
+ const normAutofit = getChild(bodyPr, "normAutofit");
1391
+ const hasSpAutofit = getChild(bodyPr, "spAutoFit") !== void 0;
1392
+ const hasNoAutofit = getChild(bodyPr, "noAutofit") !== void 0;
1393
+ const fontScale = numericAttr(normAutofit, "fontScale");
1394
+ const lnSpcReduction = numericAttr(normAutofit, "lnSpcReduction");
1395
+ const properties = {
1396
+ ...marginLeft !== void 0 ? { marginLeft: emu(marginLeft) } : {},
1397
+ ...marginRight !== void 0 ? { marginRight: emu(marginRight) } : {},
1398
+ ...marginTop !== void 0 ? { marginTop: emu(marginTop) } : {},
1399
+ ...marginBottom !== void 0 ? { marginBottom: emu(marginBottom) } : {},
1400
+ ...anchor !== void 0 ? { anchor } : {},
1401
+ ...wrap !== void 0 ? { wrap } : {},
1402
+ ...normAutofit !== void 0 ? {
1403
+ autoFit: "normAutofit",
1404
+ fontScale: fontScale !== void 0 ? fontScale / 1e5 : 1,
1405
+ lnSpcReduction: lnSpcReduction !== void 0 ? lnSpcReduction / 1e5 : 0
1406
+ } : hasSpAutofit ? { autoFit: "spAutofit", fontScale: 1, lnSpcReduction: 0 } : hasNoAutofit ? { autoFit: "noAutofit", fontScale: 1, lnSpcReduction: 0 } : {},
1407
+ ...numCol !== void 0 ? { numCol: Math.max(1, numCol) } : {},
1408
+ ...vert !== void 0 ? { vert } : {}
1409
+ };
1410
+ return Object.keys(properties).length > 0 ? properties : void 0;
1411
+ }
1412
+ function parseWrap(value) {
1413
+ return parseEnumValue(value, WRAP_VALUES);
1414
+ }
1415
+ function parseVerticalType(value) {
1416
+ return parseEnumValue(value, VERTICAL_VALUES);
1417
+ }
1418
+ function parseParagraph(p, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex, orderedChildren) {
1419
+ const properties = parseParagraphProperties(getChild(p, "pPr"));
1420
+ const runs = parseRunsInOrder(
1421
+ p,
1422
+ partPath,
1423
+ nextId,
1424
+ ownerNodeId,
1425
+ ownerOrderingSlot,
1426
+ paragraphIndex,
1427
+ orderedChildren
1428
+ );
1429
+ const rawSidecars = collectUnknownSidecars(p, KNOWN_PARAGRAPH_CHILDREN, nextId);
1430
+ return {
1431
+ runs,
1432
+ ...properties !== void 0 ? { properties } : {},
1433
+ handle: {
1434
+ partPath,
1435
+ nodeId: textNodeId("paragraph", ownerNodeId, ownerOrderingSlot, paragraphIndex),
1436
+ orderingSlot: paragraphIndex
1437
+ },
1438
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
1439
+ };
1440
+ }
1441
+ function parseRunsInOrder(p, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex, orderedChildren) {
1442
+ const rList = getChildArray(p, "r");
1443
+ const fldList = getChildArray(p, "fld");
1444
+ const brList = getChildArray(p, "br");
1445
+ if (orderedChildren === void 0) {
1446
+ return [
1447
+ ...rList.map(
1448
+ (r, runIndex) => parseRun(r, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex, runIndex)
1449
+ ),
1450
+ ...fldList.map(
1451
+ (fld, index) => parseRun(
1452
+ fld,
1453
+ partPath,
1454
+ nextId,
1455
+ ownerNodeId,
1456
+ ownerOrderingSlot,
1457
+ paragraphIndex,
1458
+ rList.length + index
1459
+ )
1460
+ ),
1461
+ ...brList.map(
1462
+ (br, index) => parseBreakRun(
1463
+ br,
1464
+ partPath,
1465
+ nextId,
1466
+ ownerNodeId,
1467
+ ownerOrderingSlot,
1468
+ paragraphIndex,
1469
+ rList.length + fldList.length + index
1470
+ )
1471
+ )
1472
+ ];
1473
+ }
1474
+ const counters = {};
1475
+ const runs = [];
1476
+ for (const child of orderedChildren) {
1477
+ const tag = orderedLocalName(child);
1478
+ if (tag !== "r" && tag !== "fld" && tag !== "br") continue;
1479
+ const index = counters[tag] ?? 0;
1480
+ counters[tag] = index + 1;
1481
+ const runIndex = runs.length;
1482
+ if (tag === "r" && rList[index] !== void 0) {
1483
+ runs.push(
1484
+ parseRun(
1485
+ rList[index],
1486
+ partPath,
1487
+ nextId,
1488
+ ownerNodeId,
1489
+ ownerOrderingSlot,
1490
+ paragraphIndex,
1491
+ runIndex
1492
+ )
1493
+ );
1494
+ } else if (tag === "fld" && fldList[index] !== void 0) {
1495
+ runs.push(
1496
+ parseRun(
1497
+ fldList[index],
1498
+ partPath,
1499
+ nextId,
1500
+ ownerNodeId,
1501
+ ownerOrderingSlot,
1502
+ paragraphIndex,
1503
+ runIndex
1504
+ )
1505
+ );
1506
+ } else if (tag === "br" && brList[index] !== void 0) {
1507
+ runs.push(
1508
+ parseBreakRun(
1509
+ brList[index],
1510
+ partPath,
1511
+ nextId,
1512
+ ownerNodeId,
1513
+ ownerOrderingSlot,
1514
+ paragraphIndex,
1515
+ runIndex
1516
+ )
1517
+ );
1518
+ }
1519
+ }
1520
+ return runs;
1521
+ }
1522
+ function parseParagraphProperties(pPr) {
1523
+ if (!pPr) return void 0;
1524
+ const alignToken = getAttr(pPr, "algn");
1525
+ const align = alignToken !== void 0 ? ALIGN_MAP[alignToken] : void 0;
1526
+ const level = numericAttr(pPr, "lvl");
1527
+ const lineSpacing = parseSpacing(getChild(pPr, "lnSpc"));
1528
+ const spaceBefore = parseSpacing(getChild(pPr, "spcBef"));
1529
+ const spaceAfter = parseSpacing(getChild(pPr, "spcAft"));
1530
+ const marginLeft = numericAttr(pPr, "marL");
1531
+ const indent = numericAttr(pPr, "indent");
1532
+ const bullet = parseBullet(pPr);
1533
+ const bulletFont = getAttr(getChild(pPr, "buFont"), "typeface");
1534
+ const bulletColor = parseColorElement(getChild(pPr, "buClr"));
1535
+ const bulletSizePct = numericAttr(getChild(pPr, "buSzPct"), "val");
1536
+ const tabStops = parseTabStops(pPr);
1537
+ const defaultRunProperties = parseRunProperties(getChild(pPr, "defRPr"));
1538
+ const properties = {
1539
+ ...align !== void 0 ? { align } : {},
1540
+ ...level !== void 0 ? { level } : {},
1541
+ ...lineSpacing !== void 0 ? { lineSpacing } : {},
1542
+ ...spaceBefore !== void 0 ? { spaceBefore } : {},
1543
+ ...spaceAfter !== void 0 ? { spaceAfter } : {},
1544
+ ...marginLeft !== void 0 ? { marginLeft: emu(marginLeft) } : {},
1545
+ ...indent !== void 0 ? { indent: emu(indent) } : {},
1546
+ ...bullet !== void 0 ? { bullet } : {},
1547
+ ...bulletFont !== void 0 ? { bulletFont } : {},
1548
+ ...bulletColor !== void 0 ? { bulletColor } : {},
1549
+ ...bulletSizePct !== void 0 ? { bulletSizePct } : {},
1550
+ ...tabStops.length > 0 ? { tabStops } : {},
1551
+ ...defaultRunProperties !== void 0 ? { defaultRunProperties } : {}
1552
+ };
1553
+ return Object.keys(properties).length > 0 ? properties : void 0;
1554
+ }
1555
+ function parseTabStops(pPr) {
1556
+ return getChildArray(getChild(pPr, "tabLst"), "tab").map((tab) => ({
1557
+ position: emu(numericAttr(tab, "pos") ?? 0),
1558
+ alignment: unsafeOoxmlBoundaryAssertion(getAttr(tab, "algn")) ?? "l"
1559
+ }));
1560
+ }
1561
+ function parseSpacing(node) {
1562
+ const points = numericAttr(getChild(node, "spcPts"), "val");
1563
+ if (points !== void 0) return { type: "pts", value: asHundredthPt(points) };
1564
+ const percent = numericAttr(getChild(node, "spcPct"), "val");
1565
+ if (percent !== void 0) return { type: "pct", value: percent };
1566
+ return void 0;
1567
+ }
1568
+ function parseBullet(pPr) {
1569
+ if (pPr === void 0) return void 0;
1570
+ if (getChild(pPr, "buNone") !== void 0) return { type: "none" };
1571
+ const buChar = getChild(pPr, "buChar");
1572
+ if (buChar !== void 0) {
1573
+ return { type: "char", char: decodeXmlCharRef(getAttr(buChar, "char") ?? "\u2022") };
1574
+ }
1575
+ const buAutoNum = getChild(pPr, "buAutoNum");
1576
+ if (buAutoNum !== void 0) {
1577
+ const scheme = getAttr(buAutoNum, "type") ?? "arabicPeriod";
1578
+ return {
1579
+ type: "autoNum",
1580
+ scheme: parseEnumValueWithDefault(scheme, VALID_AUTO_NUM_SCHEMES, "arabicPeriod"),
1581
+ startAt: numericAttr(buAutoNum, "startAt") ?? 1
1582
+ };
1583
+ }
1584
+ return void 0;
1585
+ }
1586
+ function decodeXmlCharRef(value) {
1587
+ return value.replace(
1588
+ /&#x([0-9a-fA-F]+);|&#([0-9]+);/g,
1589
+ (_match, hex, decimal) => String.fromCodePoint(parseInt(hex ?? decimal ?? "0", hex !== void 0 ? 16 : 10))
1590
+ );
1591
+ }
1592
+ function parseRun(r, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex, runIndex) {
1593
+ const properties = parseRunProperties(getChild(r, "rPr"));
1594
+ const rawSidecars = collectRunSidecars(r, nextId);
1595
+ return {
1596
+ kind: "textRun",
1597
+ text: decodeXmlCharRef(getChildText(r, "t") ?? ""),
1598
+ ...properties !== void 0 ? { properties } : {},
1599
+ handle: {
1600
+ partPath,
1601
+ nodeId: textNodeId("run", ownerNodeId, ownerOrderingSlot, paragraphIndex, runIndex),
1602
+ orderingSlot: runIndex
1603
+ },
1604
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
1605
+ };
1606
+ }
1607
+ function parseBreakRun(br, partPath, nextId, ownerNodeId, ownerOrderingSlot, paragraphIndex, runIndex) {
1608
+ const properties = parseRunProperties(getChild(br, "rPr"));
1609
+ return {
1610
+ kind: "textRun",
1611
+ text: "\n",
1612
+ ...properties !== void 0 ? { properties } : {},
1613
+ handle: {
1614
+ partPath,
1615
+ nodeId: textNodeId("run", ownerNodeId, ownerOrderingSlot, paragraphIndex, runIndex),
1616
+ orderingSlot: runIndex
1617
+ }
1618
+ };
1619
+ }
1620
+ function parseRunProperties(rPr) {
1621
+ if (!rPr) return void 0;
1622
+ const bold = getAttr(rPr, "b");
1623
+ const italic = getAttr(rPr, "i");
1624
+ const underline = getAttr(rPr, "u");
1625
+ const strike = getAttr(rPr, "strike");
1626
+ const baseline = numericAttr(rPr, "baseline");
1627
+ const size = numericAttr(rPr, "sz");
1628
+ const typeface = getAttr(getChild(rPr, "latin"), "typeface");
1629
+ const typefaceEa = getAttr(getChild(rPr, "ea"), "typeface");
1630
+ const typefaceCs = getAttr(getChild(rPr, "cs"), "typeface");
1631
+ const hasHyperlink = getChild(rPr, "hlinkClick") !== void 0;
1632
+ const color = parseColorElement(getChild(rPr, "solidFill"));
1633
+ const properties = {
1634
+ ...bold !== void 0 ? { bold: isTrue(bold) } : {},
1635
+ ...italic !== void 0 ? { italic: isTrue(italic) } : {},
1636
+ ...underline !== void 0 ? { underline: underline !== "none" } : hasHyperlink ? { underline: true } : {},
1637
+ ...strike !== void 0 ? { strikethrough: strike !== "noStrike" } : {},
1638
+ ...baseline !== void 0 ? { baseline: baseline / 1e3 } : {},
1639
+ // `a:rPr@sz` is in 1/100 pt unit. Convert to pt and save.
1640
+ ...size !== void 0 ? { fontSize: asPt(size / 100) } : {},
1641
+ ...typeface !== void 0 ? { typeface } : {},
1642
+ ...typefaceEa !== void 0 ? { typefaceEa } : {},
1643
+ ...typefaceCs !== void 0 ? { typefaceCs } : {},
1644
+ ...color !== void 0 ? { color } : hasHyperlink ? { color: { kind: "scheme", scheme: "hlink" } } : {}
1645
+ };
1646
+ return Object.keys(properties).length > 0 ? properties : void 0;
1647
+ }
1648
+ function collectRunSidecars(r, nextId) {
1649
+ const runLevel = collectUnknownSidecars(r, KNOWN_RUN_CHILDREN, nextId);
1650
+ const propLevel = collectUnknownSidecars(getChild(r, "rPr"), KNOWN_RUN_PROPERTY_CHILDREN, nextId);
1651
+ return [...runLevel, ...propLevel];
1652
+ }
1653
+ function emu(value) {
1654
+ return asEmu(value);
1655
+ }
1656
+ function textNodeId(kind, ownerNodeId, ownerOrderingSlot, paragraphIndex, runIndex) {
1657
+ const owner = ownerNodeId !== void 0 ? `shape:${ownerNodeId}` : `shapeSlot:${ownerOrderingSlot}`;
1658
+ const suffix = kind === "paragraph" ? `p:${paragraphIndex}` : `p:${paragraphIndex}:r:${runIndex}`;
1659
+ return asSourceNodeId(`text:${owner}:${suffix}`);
1660
+ }
1661
+ function orderedKey(node) {
1662
+ return Object.keys(node).find((key) => key !== ":@");
1663
+ }
1664
+ function orderedLocalName(node) {
1665
+ const key = orderedKey(node);
1666
+ return key !== void 0 ? localName(key) : void 0;
1667
+ }
1668
+
1669
+ // src/reader/shape-tree.ts
1670
+ var KNOWN_SHAPE_CHILDREN = /* @__PURE__ */ new Set(["nvSpPr", "spPr", "style", "txBody"]);
1671
+ var KNOWN_CONNECTOR_CHILDREN = /* @__PURE__ */ new Set(["nvCxnSpPr", "spPr", "style"]);
1672
+ var KNOWN_GROUP_CHILDREN = /* @__PURE__ */ new Set(["nvGrpSpPr", "grpSpPr"]);
1673
+ var KNOWN_PICTURE_CHILDREN = /* @__PURE__ */ new Set(["nvPicPr", "blipFill", "spPr"]);
1674
+ var KNOWN_BLIP_FILL_CHILDREN = /* @__PURE__ */ new Set([
1675
+ "blip",
1676
+ "srcRect",
1677
+ "stretch",
1678
+ "tile"
1679
+ ]);
1680
+ var KNOWN_BLIP_CHILDREN = /* @__PURE__ */ new Set([
1681
+ "grayscl",
1682
+ "biLevel",
1683
+ "blur",
1684
+ "lum",
1685
+ "duotone",
1686
+ "clrChange"
1687
+ ]);
1688
+ var KNOWN_EFFECT_CHILDREN = /* @__PURE__ */ new Set([
1689
+ "outerShdw",
1690
+ "innerShdw",
1691
+ "glow",
1692
+ "softEdge"
1693
+ ]);
1694
+ var KNOWN_GRAPHIC_FRAME_CHILDREN = /* @__PURE__ */ new Set([
1695
+ "nvGraphicFramePr",
1696
+ "xfrm",
1697
+ "graphic"
1698
+ ]);
1699
+ var KNOWN_GRAPHIC_CHILDREN = /* @__PURE__ */ new Set(["graphicData"]);
1700
+ var KNOWN_GRAPHIC_DATA_CHILDREN = /* @__PURE__ */ new Set(["tbl"]);
1701
+ var KNOWN_TABLE_CHILDREN = /* @__PURE__ */ new Set(["tblPr", "tblGrid", "tr"]);
1702
+ var KNOWN_TABLE_CELL_CHILDREN = /* @__PURE__ */ new Set(["txBody", "tcPr"]);
1703
+ var KNOWN_TABLE_CELL_PROPERTIES_CHILDREN = /* @__PURE__ */ new Set([
1704
+ "lnL",
1705
+ "lnR",
1706
+ "lnT",
1707
+ "lnB",
1708
+ "solidFill",
1709
+ "noFill",
1710
+ "gradFill",
1711
+ "blipFill",
1712
+ "pattFill",
1713
+ "grpFill"
1714
+ ]);
1715
+ var KNOWN_SP_PR_CHILDREN = /* @__PURE__ */ new Set([
1716
+ "xfrm",
1717
+ "prstGeom",
1718
+ "solidFill",
1719
+ "noFill",
1720
+ "gradFill",
1721
+ "blipFill",
1722
+ "pattFill",
1723
+ "grpFill",
1724
+ "ln",
1725
+ "effectLst"
1726
+ ]);
1727
+ var SHAPE_TREE_NODE_TAGS = /* @__PURE__ */ new Set([
1728
+ "sp",
1729
+ "pic",
1730
+ "cxnSp",
1731
+ "grpSp",
1732
+ "graphicFrame"
1733
+ ]);
1734
+ var CHART_GRAPHIC_DATA_URIS = /* @__PURE__ */ new Set([
1735
+ "http://schemas.openxmlformats.org/drawingml/2006/chart",
1736
+ "http://purl.oclc.org/ooxml/drawingml/chart"
1737
+ ]);
1738
+ var SMARTART_DIAGRAM_URIS = /* @__PURE__ */ new Set([
1739
+ "http://schemas.openxmlformats.org/drawingml/2006/diagram",
1740
+ "http://purl.oclc.org/ooxml/drawingml/diagram"
1741
+ ]);
1742
+ function parseShapeTree(spTree, partPath, nextId, orderedChildren) {
1743
+ if (!spTree) return [];
1744
+ if (orderedChildren !== void 0) {
1745
+ return parseShapeTreeOrdered(spTree, partPath, nextId, orderedChildren);
1746
+ }
1747
+ const nodes = [];
1748
+ let orderingSlot = 0;
1749
+ for (const key of Object.keys(spTree)) {
1750
+ if (key.startsWith("@_")) continue;
1751
+ if (key === "#text") continue;
1752
+ const local = localName(key);
1753
+ if (local === "nvGrpSpPr" || local === "grpSpPr") continue;
1754
+ const value = spTree[key];
1755
+ const items = Array.isArray(value) ? value : [value];
1756
+ for (const item of items) {
1757
+ const node = unsafeOoxmlBoundaryAssertion(item);
1758
+ if (local === "sp") {
1759
+ nodes.push(parseShape(node, partPath, nextId, orderingSlot));
1760
+ } else if (local === "pic") {
1761
+ nodes.push(parseImage(node, partPath, nextId, orderingSlot));
1762
+ } else if (local === "cxnSp") {
1763
+ nodes.push(parseConnector(node, partPath, nextId, orderingSlot));
1764
+ } else if (local === "grpSp") {
1765
+ nodes.push(parseGroup(node, partPath, nextId, orderingSlot));
1766
+ } else if (local === "graphicFrame") {
1767
+ nodes.push(parseGraphicFrame(node, partPath, nextId, orderingSlot));
1768
+ } else if (local === "AlternateContent") {
1769
+ const parsed = parseAlternateContent(node, partPath, nextId, orderingSlot);
1770
+ nodes.push(...parsed);
1771
+ } else {
1772
+ nodes.push(parseRawShapeNode(key, node, partPath, nextId, orderingSlot));
1773
+ }
1774
+ orderingSlot++;
1775
+ }
1776
+ }
1777
+ return nodes;
1778
+ }
1779
+ function parseShapeTreeOrdered(spTree, partPath, nextId, orderedChildren) {
1780
+ const nodes = [];
1781
+ const tagCounters = {};
1782
+ let orderingSlot = 0;
1783
+ for (const child of orderedChildren) {
1784
+ const key = Object.keys(child).find((candidate) => candidate !== ":@");
1785
+ if (key === void 0) continue;
1786
+ const local = localName(key);
1787
+ if (local === "AlternateContent") {
1788
+ const index2 = tagCounters[local] ?? 0;
1789
+ tagCounters[local] = index2 + 1;
1790
+ const alternateContents = getChildArray(spTree, "AlternateContent");
1791
+ const alternateContent = alternateContents[index2];
1792
+ if (alternateContent !== void 0) {
1793
+ nodes.push(...parseAlternateContent(alternateContent, partPath, nextId, orderingSlot));
1794
+ orderingSlot++;
1795
+ }
1796
+ continue;
1797
+ }
1798
+ if (!SHAPE_TREE_NODE_TAGS.has(local)) continue;
1799
+ const index = tagCounters[local] ?? 0;
1800
+ tagCounters[local] = index + 1;
1801
+ const node = getChildArray(spTree, local)[index];
1802
+ if (node === void 0) continue;
1803
+ nodes.push(parseShapeTreeNode(local, node, child, partPath, nextId, orderingSlot));
1804
+ orderingSlot++;
1805
+ }
1806
+ return nodes;
1807
+ }
1808
+ function parseShapeTreeNode(local, node, orderedNode, partPath, nextId, orderingSlot) {
1809
+ if (local === "sp") return parseShape(node, partPath, nextId, orderingSlot, orderedNode);
1810
+ if (local === "pic") return parseImage(node, partPath, nextId, orderingSlot);
1811
+ if (local === "cxnSp") {
1812
+ return parseConnector(node, partPath, nextId, orderingSlot, orderedNode);
1813
+ }
1814
+ if (local === "grpSp") {
1815
+ const orderedGroupChildren = unsafeOoxmlBoundaryAssertion(orderedNode?.[local]);
1816
+ return parseGroup(node, partPath, nextId, orderingSlot, orderedGroupChildren);
1817
+ }
1818
+ if (local === "graphicFrame") {
1819
+ return parseGraphicFrame(node, partPath, nextId, orderingSlot, orderedNode);
1820
+ }
1821
+ return parseRawShapeNode(`p:${local}`, node, partPath, nextId, orderingSlot);
1822
+ }
1823
+ function parseShape(sp, partPath, nextId, orderingSlot, orderedNode) {
1824
+ const nvSpPr = getChild(sp, "nvSpPr");
1825
+ const cNvPr = getChild(nvSpPr, "cNvPr");
1826
+ const nodeId = sourceNodeId(cNvPr);
1827
+ const name = getAttr(cNvPr, "name");
1828
+ const placeholder = parsePlaceholder(getChild(getChild(nvSpPr, "nvPr"), "ph"));
1829
+ const spPr = getChild(sp, "spPr");
1830
+ const transform = parseTransform(spPr);
1831
+ const geometry = parseGeometry(spPr, orderedNestedChildChildren(orderedNode, "sp", "spPr"));
1832
+ const fill = parseFill(spPr, nextId);
1833
+ const outline = parseOutline(spPr, nextId);
1834
+ const effects = parseEffectList(getChild(spPr, "effectLst"));
1835
+ const style = parseShapeStyle(getChild(sp, "style"));
1836
+ const textBody = parseTextBody(
1837
+ getChild(sp, "txBody"),
1838
+ partPath,
1839
+ nextId,
1840
+ nodeId,
1841
+ orderingSlot,
1842
+ orderedNestedChildChildren(orderedNode, "sp", "txBody")
1843
+ );
1844
+ const rawSidecars = [
1845
+ ...collectUnknownSidecars(sp, KNOWN_SHAPE_CHILDREN, nextId),
1846
+ ...collectUnknownSidecars(spPr, KNOWN_SP_PR_CHILDREN, nextId),
1847
+ ...collectEffectSidecars(spPr, effects, nextId)
1848
+ ];
1849
+ return {
1850
+ kind: "shape",
1851
+ ...nodeId !== void 0 ? { nodeId } : {},
1852
+ ...name !== void 0 ? { name } : {},
1853
+ ...transform !== void 0 ? { transform } : {},
1854
+ ...geometry !== void 0 ? { geometry } : {},
1855
+ ...fill !== void 0 ? { fill } : {},
1856
+ ...outline !== void 0 ? { outline } : {},
1857
+ ...effects !== void 0 ? { effects } : {},
1858
+ ...style !== void 0 ? { style } : {},
1859
+ ...textBody !== void 0 ? { textBody } : {},
1860
+ ...placeholder !== void 0 ? { placeholder } : {},
1861
+ handle: { partPath, ...nodeId !== void 0 ? { nodeId } : {}, orderingSlot },
1862
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
1863
+ };
1864
+ }
1865
+ function parseConnector(cxnSp, partPath, nextId, orderingSlot, orderedNode) {
1866
+ const nvCxnSpPr = getChild(cxnSp, "nvCxnSpPr");
1867
+ const cNvPr = getChild(nvCxnSpPr, "cNvPr");
1868
+ const nodeId = sourceNodeId(cNvPr);
1869
+ const name = getAttr(cNvPr, "name");
1870
+ const spPr = getChild(cxnSp, "spPr");
1871
+ const transform = parseTransform(spPr);
1872
+ const geometry = parseGeometry(spPr, orderedNestedChildChildren(orderedNode, "cxnSp", "spPr"));
1873
+ const outline = parseOutline(spPr, nextId);
1874
+ const effects = parseEffectList(getChild(spPr, "effectLst"));
1875
+ const style = parseShapeStyle(getChild(cxnSp, "style"));
1876
+ const rawSidecars = [
1877
+ ...collectUnknownSidecars(cxnSp, KNOWN_CONNECTOR_CHILDREN, nextId),
1878
+ ...collectUnknownSidecars(spPr, KNOWN_SP_PR_CHILDREN, nextId),
1879
+ ...collectEffectSidecars(spPr, effects, nextId)
1880
+ ];
1881
+ return {
1882
+ kind: "connector",
1883
+ ...nodeId !== void 0 ? { nodeId } : {},
1884
+ ...name !== void 0 ? { name } : {},
1885
+ ...transform !== void 0 ? { transform } : {},
1886
+ ...geometry !== void 0 ? { geometry } : {},
1887
+ ...outline !== void 0 ? { outline } : {},
1888
+ ...effects !== void 0 ? { effects } : {},
1889
+ ...style !== void 0 ? { style } : {},
1890
+ handle: { partPath, ...nodeId !== void 0 ? { nodeId } : {}, orderingSlot },
1891
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
1892
+ };
1893
+ }
1894
+ function parseShapeStyle(style) {
1895
+ if (style === void 0) return void 0;
1896
+ const fillRef = parseStyleReference(getChild(style, "fillRef"));
1897
+ const lineRef = parseStyleReference(getChild(style, "lnRef"));
1898
+ const effectRef = parseStyleReference(getChild(style, "effectRef"));
1899
+ const parsed = {
1900
+ ...fillRef !== void 0 ? { fillRef } : {},
1901
+ ...lineRef !== void 0 ? { lineRef } : {},
1902
+ ...effectRef !== void 0 ? { effectRef } : {}
1903
+ };
1904
+ return Object.keys(parsed).length > 0 ? parsed : void 0;
1905
+ }
1906
+ function parseStyleReference(ref) {
1907
+ if (ref === void 0) return void 0;
1908
+ const index = numericAttr(ref, "idx") ?? 0;
1909
+ const color = parseColorElement(ref);
1910
+ return {
1911
+ index,
1912
+ ...color !== void 0 ? { color } : {}
1913
+ };
1914
+ }
1915
+ function parseGroup(grpSp, partPath, nextId, orderingSlot, orderedChildren) {
1916
+ const nvGrpSpPr = getChild(grpSp, "nvGrpSpPr");
1917
+ const cNvPr = getChild(nvGrpSpPr, "cNvPr");
1918
+ const nodeId = sourceNodeId(cNvPr);
1919
+ const name = getAttr(cNvPr, "name");
1920
+ const grpSpPr = getChild(grpSp, "grpSpPr");
1921
+ const transform = parseTransform(grpSpPr);
1922
+ const childTransform = parseChildTransform(grpSpPr, transform);
1923
+ const fill = parseFill(grpSpPr, nextId);
1924
+ const effects = parseEffectList(getChild(grpSpPr, "effectLst"));
1925
+ const rawSidecars = [
1926
+ ...collectUnknownSidecars(grpSp, KNOWN_GROUP_CHILDREN, nextId),
1927
+ ...collectUnknownSidecars(grpSpPr, KNOWN_SP_PR_CHILDREN, nextId),
1928
+ ...collectEffectSidecars(grpSpPr, effects, nextId)
1929
+ ];
1930
+ return {
1931
+ kind: "group",
1932
+ ...nodeId !== void 0 ? { nodeId } : {},
1933
+ ...name !== void 0 ? { name } : {},
1934
+ ...transform !== void 0 ? { transform } : {},
1935
+ ...childTransform !== void 0 ? { childTransform } : {},
1936
+ ...fill !== void 0 ? { fill } : {},
1937
+ ...effects !== void 0 ? { effects } : {},
1938
+ children: parseShapeTree(grpSp, partPath, nextId, orderedChildren),
1939
+ handle: { partPath, ...nodeId !== void 0 ? { nodeId } : {}, orderingSlot },
1940
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
1941
+ };
1942
+ }
1943
+ function parseImage(pic, partPath, nextId, orderingSlot) {
1944
+ const cNvPr = getChild(getChild(pic, "nvPicPr"), "cNvPr");
1945
+ const nodeId = sourceNodeId(cNvPr);
1946
+ const name = getAttr(cNvPr, "name");
1947
+ const blipFill = getChild(pic, "blipFill");
1948
+ const blip = getChild(blipFill, "blip");
1949
+ const embed = getNamespacedAttr(blip, "embed");
1950
+ const crop = parseCrop(getChild(blipFill, "srcRect"));
1951
+ const stretch = parseStretch(getChild(blipFill, "stretch"));
1952
+ const tile = parseImageFillTile(getChild(blipFill, "tile"));
1953
+ const blipEffects = parseBlipEffects(blip);
1954
+ const spPr = getChild(pic, "spPr");
1955
+ const transform = parseTransform(spPr);
1956
+ const effects = parseEffectList(getChild(spPr, "effectLst"));
1957
+ const rawSidecars = [
1958
+ ...collectUnknownSidecars(pic, KNOWN_PICTURE_CHILDREN, nextId),
1959
+ ...collectUnknownSidecars(spPr, KNOWN_SP_PR_CHILDREN, nextId),
1960
+ ...collectEffectSidecars(spPr, effects, nextId),
1961
+ // Retains fill mode such as `a:stretch` / `a:tile` and recolor operation under blip.
1962
+ ...collectUnknownSidecars(blipFill, KNOWN_BLIP_FILL_CHILDREN, nextId),
1963
+ ...collectBlipEffectSidecars(blip, blipEffects, nextId)
1964
+ ];
1965
+ return {
1966
+ kind: "image",
1967
+ ...nodeId !== void 0 ? { nodeId } : {},
1968
+ ...name !== void 0 ? { name } : {},
1969
+ ...transform !== void 0 ? { transform } : {},
1970
+ ...embed !== void 0 ? { blipRelationshipId: asRelationshipId(embed) } : {},
1971
+ ...crop !== void 0 ? { crop } : {},
1972
+ ...stretch !== void 0 ? { stretch } : {},
1973
+ ...tile !== void 0 ? { tile } : {},
1974
+ ...effects !== void 0 ? { effects } : {},
1975
+ ...blipEffects !== void 0 ? { blipEffects } : {},
1976
+ handle: {
1977
+ partPath,
1978
+ ...nodeId !== void 0 ? { nodeId } : {},
1979
+ ...embed !== void 0 ? { relationshipId: asRelationshipId(embed) } : {},
1980
+ orderingSlot
1981
+ },
1982
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
1983
+ };
1984
+ }
1985
+ function collectEffectSidecars(spPr, effects, nextId) {
1986
+ const effectList = getChild(spPr, "effectLst");
1987
+ if (effectList === void 0) return [];
1988
+ const sidecars = collectUnknownSidecars(effectList, KNOWN_EFFECT_CHILDREN, nextId);
1989
+ const supportedChildren = [
1990
+ ["outerShdw", effects?.outerShadow],
1991
+ ["innerShdw", effects?.innerShadow],
1992
+ ["glow", effects?.glow],
1993
+ ["softEdge", effects?.softEdge]
1994
+ ];
1995
+ for (const [name, parsed] of supportedChildren) {
1996
+ const node = getChild(effectList, name);
1997
+ if (node !== void 0 && parsed === void 0) {
1998
+ sidecars.push(makeSidecar(`a:${name}`, node, nextId));
1999
+ }
2000
+ }
2001
+ return sidecars;
2002
+ }
2003
+ function collectBlipEffectSidecars(blip, effects, nextId) {
2004
+ if (blip === void 0) return [];
2005
+ const sidecars = collectUnknownSidecars(blip, KNOWN_BLIP_CHILDREN, nextId);
2006
+ const supportedChildren = [
2007
+ ["grayscl", effects?.grayscale === true],
2008
+ ["biLevel", effects?.biLevel],
2009
+ ["blur", effects?.blur],
2010
+ ["lum", effects?.lum],
2011
+ ["duotone", effects?.duotone],
2012
+ ["clrChange", effects?.clrChange]
2013
+ ];
2014
+ for (const [name, parsed] of supportedChildren) {
2015
+ const node = getChild(blip, name);
2016
+ if (node !== void 0 && (parsed === void 0 || parsed === false)) {
2017
+ sidecars.push(makeSidecar(`a:${name}`, node, nextId));
2018
+ }
2019
+ }
2020
+ return sidecars;
2021
+ }
2022
+ function parseGraphicFrame(graphicFrame, partPath, nextId, orderingSlot, orderedNode) {
2023
+ const graphic = getChild(graphicFrame, "graphic");
2024
+ const graphicData = getChild(graphic, "graphicData");
2025
+ const uri = getAttr(graphicData, "uri");
2026
+ if (uri !== void 0 && CHART_GRAPHIC_DATA_URIS.has(uri)) {
2027
+ const parsedChart = parseChartGraphicFrame(graphicFrame, partPath, nextId, orderingSlot);
2028
+ if (parsedChart !== void 0) return parsedChart;
2029
+ }
2030
+ if (uri !== void 0 && SMARTART_DIAGRAM_URIS.has(uri)) {
2031
+ const parsedSmartArt = parseSmartArtGraphicFrame(graphicFrame, partPath, nextId, orderingSlot);
2032
+ if (parsedSmartArt !== void 0) return parsedSmartArt;
2033
+ }
2034
+ const table = getChild(graphicData, "tbl");
2035
+ if (table === void 0) {
2036
+ return parseRawShapeNode("p:graphicFrame", graphicFrame, partPath, nextId, orderingSlot);
2037
+ }
2038
+ const orderedGraphicChildren = orderedNestedChildChildren(orderedNode, "graphicFrame", "graphic");
2039
+ const orderedGraphicDataChildren = orderedChildChildren2(orderedGraphicChildren, "graphicData");
2040
+ const orderedTableChildren = orderedChildChildren2(orderedGraphicDataChildren, "tbl");
2041
+ const parsedTable = parseTable(
2042
+ table,
2043
+ graphicFrame,
2044
+ partPath,
2045
+ nextId,
2046
+ orderingSlot,
2047
+ orderedTableChildren
2048
+ );
2049
+ if (parsedTable === void 0) {
2050
+ return parseRawShapeNode("p:graphicFrame", graphicFrame, partPath, nextId, orderingSlot);
2051
+ }
2052
+ return parsedTable;
2053
+ }
2054
+ function parseAlternateContent(alternateContent, partPath, nextId, orderingSlot) {
2055
+ const branches = [
2056
+ ...getChildArray(alternateContent, "Choice"),
2057
+ ...getChildArray(alternateContent, "Fallback")
2058
+ ];
2059
+ for (const branch of branches) {
2060
+ const parsed = parseAlternateContentBranch(branch, partPath, nextId, orderingSlot);
2061
+ if (parsed.length > 0) {
2062
+ if (parsed.every((node) => node.kind === "raw")) {
2063
+ continue;
2064
+ }
2065
+ return parsed.map(
2066
+ (node) => attachRawSidecar(node, makeSidecar("mc:AlternateContent", alternateContent, nextId))
2067
+ );
2068
+ }
2069
+ }
2070
+ return [
2071
+ parseRawShapeNode("mc:AlternateContent", alternateContent, partPath, nextId, orderingSlot)
2072
+ ];
2073
+ }
2074
+ function attachRawSidecar(node, sidecar) {
2075
+ if (node.kind === "raw") return node;
2076
+ return {
2077
+ ...node,
2078
+ rawSidecars: [...node.rawSidecars ?? [], sidecar]
2079
+ };
2080
+ }
2081
+ function parseAlternateContentBranch(branch, partPath, nextId, orderingSlot) {
2082
+ const nodes = [];
2083
+ for (const key of Object.keys(branch)) {
2084
+ if (key.startsWith("@_") || key === "#text") continue;
2085
+ const local = localName(key);
2086
+ const value = branch[key];
2087
+ const items = Array.isArray(value) ? value : [value];
2088
+ for (const item of items) {
2089
+ const node = unsafeOoxmlBoundaryAssertion(item);
2090
+ if (local === "sp") nodes.push(parseShape(node, partPath, nextId, orderingSlot));
2091
+ else if (local === "pic") nodes.push(parseImage(node, partPath, nextId, orderingSlot));
2092
+ else if (local === "cxnSp") {
2093
+ nodes.push(parseConnector(node, partPath, nextId, orderingSlot));
2094
+ } else if (local === "grpSp") {
2095
+ nodes.push(parseGroup(node, partPath, nextId, orderingSlot));
2096
+ } else if (local === "graphicFrame") {
2097
+ nodes.push(parseGraphicFrame(node, partPath, nextId, orderingSlot));
2098
+ } else {
2099
+ nodes.push(parseRawShapeNode(key, node, partPath, nextId, orderingSlot));
2100
+ }
2101
+ }
2102
+ }
2103
+ return nodes;
2104
+ }
2105
+ function parseChartGraphicFrame(graphicFrame, partPath, nextId, orderingSlot) {
2106
+ const graphic = getChild(graphicFrame, "graphic");
2107
+ const graphicData = getChild(graphic, "graphicData");
2108
+ const chart = getChild(graphicData, "chart");
2109
+ const rId = getNamespacedAttr(chart, "id") ?? getAttr(chart, "id");
2110
+ if (rId === void 0) return void 0;
2111
+ const nvGraphicFramePr = getChild(graphicFrame, "nvGraphicFramePr");
2112
+ const cNvPr = getChild(nvGraphicFramePr, "cNvPr");
2113
+ const nodeId = sourceNodeId(cNvPr);
2114
+ const name = getAttr(cNvPr, "name");
2115
+ const transform = parseTransform(graphicFrame);
2116
+ const rawSidecars = [
2117
+ ...collectUnknownSidecars(graphicFrame, KNOWN_GRAPHIC_FRAME_CHILDREN, nextId),
2118
+ ...collectUnknownSidecars(graphic, KNOWN_GRAPHIC_CHILDREN, nextId),
2119
+ ...collectUnknownSidecars(graphicData, EMPTY_KNOWN, nextId)
2120
+ ];
2121
+ return {
2122
+ kind: "chart",
2123
+ ...nodeId !== void 0 ? { nodeId } : {},
2124
+ ...name !== void 0 ? { name } : {},
2125
+ ...transform !== void 0 ? { transform } : {},
2126
+ chartRelationshipId: asRelationshipId(rId),
2127
+ handle: {
2128
+ partPath,
2129
+ ...nodeId !== void 0 ? { nodeId } : {},
2130
+ relationshipId: asRelationshipId(rId),
2131
+ orderingSlot
2132
+ },
2133
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
2134
+ };
2135
+ }
2136
+ function parseSmartArtGraphicFrame(graphicFrame, partPath, nextId, orderingSlot) {
2137
+ const graphic = getChild(graphicFrame, "graphic");
2138
+ const graphicData = getChild(graphic, "graphicData");
2139
+ const relIds = getChild(graphicData, "relIds");
2140
+ const dmRId = getNamespacedAttr(relIds, "dm") ?? getAttr(relIds, "dm");
2141
+ if (dmRId === void 0) return void 0;
2142
+ const nvGraphicFramePr = getChild(graphicFrame, "nvGraphicFramePr");
2143
+ const cNvPr = getChild(nvGraphicFramePr, "cNvPr");
2144
+ const nodeId = sourceNodeId(cNvPr);
2145
+ const name = getAttr(cNvPr, "name");
2146
+ const transform = parseTransform(graphicFrame);
2147
+ const rawSidecars = [
2148
+ ...collectUnknownSidecars(graphicFrame, KNOWN_GRAPHIC_FRAME_CHILDREN, nextId),
2149
+ ...collectUnknownSidecars(graphic, KNOWN_GRAPHIC_CHILDREN, nextId),
2150
+ ...collectUnknownSidecars(graphicData, EMPTY_KNOWN, nextId)
2151
+ ];
2152
+ return {
2153
+ kind: "smartArt",
2154
+ ...nodeId !== void 0 ? { nodeId } : {},
2155
+ ...name !== void 0 ? { name } : {},
2156
+ ...transform !== void 0 ? { transform } : {},
2157
+ dataRelationshipId: asRelationshipId(dmRId),
2158
+ handle: {
2159
+ partPath,
2160
+ ...nodeId !== void 0 ? { nodeId } : {},
2161
+ relationshipId: asRelationshipId(dmRId),
2162
+ orderingSlot
2163
+ },
2164
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
2165
+ };
2166
+ }
2167
+ function parseTable(tbl, graphicFrame, partPath, nextId, orderingSlot, orderedTableChildren) {
2168
+ const columns = parseTableColumns(getChild(tbl, "tblGrid"));
2169
+ if (columns.length === 0) return void 0;
2170
+ const nvGraphicFramePr = getChild(graphicFrame, "nvGraphicFramePr");
2171
+ const cNvPr = getChild(nvGraphicFramePr, "cNvPr");
2172
+ const nodeId = sourceNodeId(cNvPr);
2173
+ const name = getAttr(cNvPr, "name");
2174
+ const tblPr = getChild(tbl, "tblPr");
2175
+ const tableStyleId = getChildText(tblPr, "tableStyleId");
2176
+ const graphic = getChild(graphicFrame, "graphic");
2177
+ const graphicData = getChild(graphic, "graphicData");
2178
+ const transform = parseTransform(graphicFrame);
2179
+ const rows = parseTableRows(tbl, partPath, nextId, nodeId, orderingSlot, orderedTableChildren);
2180
+ const rawSidecars = [
2181
+ ...collectUnknownSidecars(graphicFrame, KNOWN_GRAPHIC_FRAME_CHILDREN, nextId),
2182
+ ...collectUnknownSidecars(graphic, KNOWN_GRAPHIC_CHILDREN, nextId),
2183
+ ...collectUnknownSidecars(graphicData, KNOWN_GRAPHIC_DATA_CHILDREN, nextId),
2184
+ ...collectUnknownSidecars(tbl, KNOWN_TABLE_CHILDREN, nextId)
2185
+ ];
2186
+ return {
2187
+ kind: "table",
2188
+ ...nodeId !== void 0 ? { nodeId } : {},
2189
+ ...name !== void 0 ? { name } : {},
2190
+ ...transform !== void 0 ? { transform } : {},
2191
+ table: {
2192
+ columns,
2193
+ rows,
2194
+ ...tableStyleId !== void 0 ? { tableStyleId } : {}
2195
+ },
2196
+ handle: { partPath, ...nodeId !== void 0 ? { nodeId } : {}, orderingSlot },
2197
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
2198
+ };
2199
+ }
2200
+ function parseTableColumns(tblGrid) {
2201
+ return getChildArray(tblGrid, "gridCol").map((col) => ({ width: emuAttr(col, "w") }));
2202
+ }
2203
+ function parseTableRows(tbl, partPath, nextId, tableNodeId, tableOrderingSlot, orderedTableChildren) {
2204
+ const orderedRows = orderedChildChildrenList(orderedTableChildren, "tr");
2205
+ return getChildArray(tbl, "tr").map((tr, rowIndex) => ({
2206
+ height: emuAttr(tr, "h"),
2207
+ cells: getChildArray(tr, "tc").map((tc, cellIndex) => {
2208
+ const orderedCells = orderedChildChildrenList(orderedRows[rowIndex], "tc");
2209
+ return parseTableCell(
2210
+ tc,
2211
+ partPath,
2212
+ nextId,
2213
+ tableNodeId,
2214
+ tableOrderingSlot,
2215
+ rowIndex,
2216
+ cellIndex,
2217
+ orderedCells[cellIndex]
2218
+ );
2219
+ })
2220
+ }));
2221
+ }
2222
+ function parseTableCell(tc, partPath, nextId, tableNodeId, tableOrderingSlot, rowIndex, cellIndex, orderedCellChildren) {
2223
+ const tcPr = getChild(tc, "tcPr");
2224
+ const textOrderingSlot = tableOrderingSlot * 1e9 + rowIndex * 1e6 + cellIndex;
2225
+ const textBody = parseTextBody(
2226
+ getChild(tc, "txBody"),
2227
+ partPath,
2228
+ nextId,
2229
+ tableNodeId,
2230
+ textOrderingSlot,
2231
+ orderedChildChildren2(orderedCellChildren, "txBody")
2232
+ );
2233
+ const fill = parseFill(tcPr, nextId);
2234
+ const borders = parseCellBorders(tcPr, nextId);
2235
+ const rawSidecars = [
2236
+ ...collectUnknownSidecars(tc, KNOWN_TABLE_CELL_CHILDREN, nextId),
2237
+ ...collectUnknownSidecars(tcPr, KNOWN_TABLE_CELL_PROPERTIES_CHILDREN, nextId)
2238
+ ];
2239
+ return {
2240
+ ...textBody !== void 0 ? { textBody } : {},
2241
+ ...fill !== void 0 ? { fill } : {},
2242
+ ...borders !== void 0 ? { borders } : {},
2243
+ gridSpan: numericAttr(tc, "gridSpan") ?? 1,
2244
+ rowSpan: numericAttr(tc, "rowSpan") ?? 1,
2245
+ hMerge: isTrue(getAttr(tc, "hMerge") ?? getAttr(tcPr, "hMerge")),
2246
+ vMerge: isTrue(getAttr(tc, "vMerge") ?? getAttr(tcPr, "vMerge")),
2247
+ ...rawSidecars.length > 0 ? { rawSidecars } : {}
2248
+ };
2249
+ }
2250
+ function parseCellBorders(tcPr, nextId) {
2251
+ const left = parseLine(getChild(tcPr, "lnL"), nextId);
2252
+ const right = parseLine(getChild(tcPr, "lnR"), nextId);
2253
+ const top = parseLine(getChild(tcPr, "lnT"), nextId);
2254
+ const bottom = parseLine(getChild(tcPr, "lnB"), nextId);
2255
+ if (left === void 0 && right === void 0 && top === void 0 && bottom === void 0) {
2256
+ return void 0;
2257
+ }
2258
+ return {
2259
+ ...top !== void 0 ? { top } : {},
2260
+ ...bottom !== void 0 ? { bottom } : {},
2261
+ ...left !== void 0 ? { left } : {},
2262
+ ...right !== void 0 ? { right } : {}
2263
+ };
2264
+ }
2265
+ function parseRawShapeNode(key, node, partPath, nextId, orderingSlot) {
2266
+ const nodeId = sourceNodeId(getChild(getChild(node, "nvSpPr"), "cNvPr"));
2267
+ return {
2268
+ kind: "raw",
2269
+ ...nodeId !== void 0 ? { nodeId } : {},
2270
+ raw: makeSidecar(key, node, nextId),
2271
+ handle: { partPath, ...nodeId !== void 0 ? { nodeId } : {}, orderingSlot }
2272
+ };
2273
+ }
2274
+ function parsePlaceholder(ph) {
2275
+ if (!ph) return void 0;
2276
+ const type = getAttr(ph, "type");
2277
+ const index = numericAttr(ph, "idx");
2278
+ if (type === void 0 && index === void 0) return void 0;
2279
+ return {
2280
+ ...type !== void 0 ? { type } : {},
2281
+ ...index !== void 0 ? { index } : {}
2282
+ };
2283
+ }
2284
+ function parseGeometry(spPr, orderedSpPr) {
2285
+ const prstGeom = getChild(spPr, "prstGeom");
2286
+ if (prstGeom) {
2287
+ const preset = getAttr(prstGeom, "prst");
2288
+ const adjustValues = parseAdjustValues(getChild(prstGeom, "avLst"));
2289
+ return preset !== void 0 ? {
2290
+ preset,
2291
+ ...Object.keys(adjustValues).length > 0 ? { adjustValues } : {}
2292
+ } : void 0;
2293
+ }
2294
+ const customPaths = parseCustomGeometry(
2295
+ getChild(spPr, "custGeom"),
2296
+ orderedChildChildren2(orderedSpPr, "custGeom")
2297
+ );
2298
+ if (customPaths !== void 0) return { kind: "custom", paths: customPaths };
2299
+ return void 0;
2300
+ }
2301
+ function parseAdjustValues(avLst) {
2302
+ const adjustValues = {};
2303
+ for (const guide of getChildArray(avLst, "gd")) {
2304
+ const name = getAttr(guide, "name");
2305
+ const formula = getAttr(guide, "fmla");
2306
+ const match = formula?.match(/val\s+(-?\d+)/);
2307
+ if (name !== void 0 && match !== void 0 && match !== null) {
2308
+ adjustValues[name] = Number(match[1]);
2309
+ }
2310
+ }
2311
+ return adjustValues;
2312
+ }
2313
+ function parseChildTransform(grpSpPr, fallback) {
2314
+ const xfrm = getChild(grpSpPr, "xfrm");
2315
+ const childOff = getChild(xfrm, "chOff");
2316
+ const childExt = getChild(xfrm, "chExt");
2317
+ const offsetX = numericAttr(childOff, "x") ?? 0;
2318
+ const offsetY = numericAttr(childOff, "y") ?? 0;
2319
+ const width = numericAttr(childExt, "cx") ?? fallback?.width;
2320
+ const height = numericAttr(childExt, "cy") ?? fallback?.height;
2321
+ if (width === void 0 || height === void 0) return void 0;
2322
+ return {
2323
+ offsetX: asEmu(offsetX),
2324
+ offsetY: asEmu(offsetY),
2325
+ width: asEmu(Number(width)),
2326
+ height: asEmu(Number(height))
2327
+ };
2328
+ }
2329
+ function parseCrop(srcRect) {
2330
+ if (!srcRect) return void 0;
2331
+ const left = numericAttr(srcRect, "l");
2332
+ const top = numericAttr(srcRect, "t");
2333
+ const right = numericAttr(srcRect, "r");
2334
+ const bottom = numericAttr(srcRect, "b");
2335
+ const crop = {
2336
+ ...left !== void 0 ? { left: asOoxmlPercent(left) } : {},
2337
+ ...top !== void 0 ? { top: asOoxmlPercent(top) } : {},
2338
+ ...right !== void 0 ? { right: asOoxmlPercent(right) } : {},
2339
+ ...bottom !== void 0 ? { bottom: asOoxmlPercent(bottom) } : {}
2340
+ };
2341
+ return Object.keys(crop).length > 0 ? crop : void 0;
2342
+ }
2343
+ function parseStretch(stretch) {
2344
+ const fillRect = getChild(stretch, "fillRect");
2345
+ if (fillRect === void 0) return void 0;
2346
+ const left = (numericAttr(fillRect, "l") ?? 0) / 1e5;
2347
+ const top = (numericAttr(fillRect, "t") ?? 0) / 1e5;
2348
+ const right = (numericAttr(fillRect, "r") ?? 0) / 1e5;
2349
+ const bottom = (numericAttr(fillRect, "b") ?? 0) / 1e5;
2350
+ if (left === 0 && top === 0 && right === 0 && bottom === 0) return void 0;
2351
+ return { left, top, right, bottom };
2352
+ }
2353
+ function sourceNodeId(cNvPr) {
2354
+ const id = getAttr(cNvPr, "id");
2355
+ return id !== void 0 ? asSourceNodeId(id) : void 0;
2356
+ }
2357
+ function emuAttr(node, attrName) {
2358
+ return asEmu(numericAttr(node, attrName) ?? 0);
2359
+ }
2360
+ var EMPTY_KNOWN = /* @__PURE__ */ new Set();
2361
+ function orderedChildChildren2(parent, childLocalName) {
2362
+ const child = parent?.find((entry) => {
2363
+ const key2 = Object.keys(entry).find((candidate) => candidate !== ":@");
2364
+ return key2 !== void 0 && localName(key2) === childLocalName;
2365
+ });
2366
+ if (child === void 0) return void 0;
2367
+ const key = Object.keys(child).find((candidate) => candidate !== ":@");
2368
+ const value = key !== void 0 ? child[key] : void 0;
2369
+ return Array.isArray(value) ? value : void 0;
2370
+ }
2371
+ function orderedChildChildrenList(parent, childLocalName) {
2372
+ if (parent === void 0) return [];
2373
+ return parent.filter((entry) => {
2374
+ const key = Object.keys(entry).find((candidate) => candidate !== ":@");
2375
+ return key !== void 0 && localName(key) === childLocalName;
2376
+ }).map((entry) => {
2377
+ const key = Object.keys(entry).find((candidate) => candidate !== ":@");
2378
+ const value = key !== void 0 ? entry[key] : void 0;
2379
+ return Array.isArray(value) ? value : void 0;
2380
+ });
2381
+ }
2382
+ function orderedNestedChildChildren(node, parentLocalName, childLocalName) {
2383
+ if (node === void 0) return void 0;
2384
+ const parentChildren = node[parentLocalName];
2385
+ return orderedChildChildren2(
2386
+ Array.isArray(parentChildren) ? parentChildren : void 0,
2387
+ childLocalName
2388
+ );
2389
+ }
2390
+
2391
+ // src/computed/color.ts
2392
+ var DEFAULT_COLOR_MAP = {
2393
+ bg1: "lt1",
2394
+ tx1: "dk1",
2395
+ bg2: "lt2",
2396
+ tx2: "dk2",
2397
+ accent1: "accent1",
2398
+ accent2: "accent2",
2399
+ accent3: "accent3",
2400
+ accent4: "accent4",
2401
+ accent5: "accent5",
2402
+ accent6: "accent6",
2403
+ hlink: "hlink",
2404
+ folHlink: "folHlink"
2405
+ };
2406
+ var FALLBACK_SCHEME_COLORS = {
2407
+ dk1: "#000000",
2408
+ lt1: "#ffffff",
2409
+ dk2: "#44546a",
2410
+ lt2: "#e7e6e6",
2411
+ accent1: "#4472c4",
2412
+ accent2: "#ed7d31",
2413
+ accent3: "#a5a5a5",
2414
+ accent4: "#ffc000",
2415
+ accent5: "#5b9bd5",
2416
+ accent6: "#70ad47",
2417
+ hlink: "#0563c1",
2418
+ folHlink: "#954f72"
2419
+ };
2420
+ function buildEffectiveColorMap(master, layoutOverride, slideOverride) {
2421
+ return {
2422
+ ...DEFAULT_COLOR_MAP,
2423
+ ...master?.mapping,
2424
+ ...layoutOverride?.mapping,
2425
+ ...slideOverride?.mapping
2426
+ };
2427
+ }
2428
+ function buildComputedColorScheme(context) {
2429
+ const colors = { ...FALLBACK_SCHEME_COLORS };
2430
+ for (const [name, color] of Object.entries(context.theme?.colorScheme?.colors ?? {})) {
2431
+ const resolved = resolveColor(context, color);
2432
+ if (resolved !== void 0) colors[name] = resolved.hex;
2433
+ }
2434
+ return colors;
2435
+ }
2436
+ function resolveColor(context, color, visited = /* @__PURE__ */ new Set()) {
2437
+ const hex = resolveBaseHex(context, color, visited);
2438
+ if (hex === void 0) return void 0;
2439
+ return applyColorTransforms(hex, color.transforms);
2440
+ }
2441
+ function resolveBaseHex(context, color, visited) {
2442
+ switch (color.kind) {
2443
+ case "srgb":
2444
+ return normalizeHex(color.hex);
2445
+ case "system":
2446
+ return normalizeHex(color.lastColor ?? "000000");
2447
+ case "scheme": {
2448
+ const mappedName = context.colorMap[color.scheme] ?? color.scheme;
2449
+ if (visited.has(mappedName)) return "#000000";
2450
+ const schemeColor = context.theme?.colorScheme?.colors[mappedName];
2451
+ return schemeColor !== void 0 ? resolveColor(context, schemeColor, /* @__PURE__ */ new Set([...visited, mappedName]))?.hex : FALLBACK_SCHEME_COLORS[mappedName];
2452
+ }
2453
+ }
2454
+ }
2455
+ function applyColorTransforms(initialHex, transforms) {
2456
+ let hex = initialHex;
2457
+ let alpha = 1;
2458
+ for (const transform of transforms ?? []) {
2459
+ switch (transform.kind) {
2460
+ case "lumMod": {
2461
+ const lumOff = transforms?.find((candidate) => candidate.kind === "lumOff");
2462
+ hex = applyLuminance(
2463
+ hex,
2464
+ Number(transform.value) / 1e5,
2465
+ Number(lumOff?.value ?? 0) / 1e5
2466
+ );
2467
+ break;
2468
+ }
2469
+ case "lumOff":
2470
+ if (!transforms?.some((candidate) => candidate.kind === "lumMod")) {
2471
+ hex = applyLuminance(hex, 1, Number(transform.value) / 1e5);
2472
+ }
2473
+ break;
2474
+ case "tint":
2475
+ hex = applyTint(hex, Number(transform.value) / 1e5);
2476
+ break;
2477
+ case "shade":
2478
+ hex = applyShade(hex, Number(transform.value) / 1e5);
2479
+ break;
2480
+ case "alpha":
2481
+ alpha = Number(transform.value) / 1e5;
2482
+ break;
2483
+ }
2484
+ }
2485
+ return { hex, alpha };
2486
+ }
2487
+ function normalizeHex(hex) {
2488
+ const normalized = hex.replace(/^#/, "").toLowerCase();
2489
+ return `#${normalized.padStart(6, "0").slice(0, 6)}`;
2490
+ }
2491
+ function applyLuminance(hex, lumMod, lumOff) {
2492
+ const { h, s, l } = hexToHsl(hex);
2493
+ return hslToHex(h, s, Math.min(1, Math.max(0, l * lumMod + lumOff)));
2494
+ }
2495
+ function applyTint(hex, tintAmount) {
2496
+ const { r, g, b } = hexToRgb(hex);
2497
+ return rgbToHex(
2498
+ Math.round(r + (255 - r) * tintAmount),
2499
+ Math.round(g + (255 - g) * tintAmount),
2500
+ Math.round(b + (255 - b) * tintAmount)
2501
+ );
2502
+ }
2503
+ function applyShade(hex, shadeAmount) {
2504
+ const { r, g, b } = hexToRgb(hex);
2505
+ return rgbToHex(
2506
+ Math.round(r * shadeAmount),
2507
+ Math.round(g * shadeAmount),
2508
+ Math.round(b * shadeAmount)
2509
+ );
2510
+ }
2511
+ function hexToRgb(hex) {
2512
+ const normalized = hex.replace("#", "");
2513
+ return {
2514
+ r: parseInt(normalized.slice(0, 2), 16),
2515
+ g: parseInt(normalized.slice(2, 4), 16),
2516
+ b: parseInt(normalized.slice(4, 6), 16)
2517
+ };
2518
+ }
2519
+ function rgbToHex(r, g, b) {
2520
+ const toHex = (value) => Math.min(255, Math.max(0, value)).toString(16).padStart(2, "0");
2521
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
2522
+ }
2523
+ function hexToHsl(hex) {
2524
+ const { r: r255, g: g255, b: b255 } = hexToRgb(hex);
2525
+ const r = r255 / 255;
2526
+ const g = g255 / 255;
2527
+ const b = b255 / 255;
2528
+ const max = Math.max(r, g, b);
2529
+ const min = Math.min(r, g, b);
2530
+ const l = (max + min) / 2;
2531
+ if (max === min) return { h: 0, s: 0, l };
2532
+ const d = max - min;
2533
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
2534
+ const h = max === r ? ((g - b) / d + (g < b ? 6 : 0)) / 6 : max === g ? ((b - r) / d + 2) / 6 : ((r - g) / d + 4) / 6;
2535
+ return { h, s, l };
2536
+ }
2537
+ function hslToHex(h, s, l) {
2538
+ if (s === 0) {
2539
+ const value = Math.round(l * 255);
2540
+ return rgbToHex(value, value, value);
2541
+ }
2542
+ const hue2rgb = (p2, q2, t) => {
2543
+ let tt = t;
2544
+ if (tt < 0) tt += 1;
2545
+ if (tt > 1) tt -= 1;
2546
+ if (tt < 1 / 6) return p2 + (q2 - p2) * 6 * tt;
2547
+ if (tt < 1 / 2) return q2;
2548
+ if (tt < 2 / 3) return p2 + (q2 - p2) * (2 / 3 - tt) * 6;
2549
+ return p2;
2550
+ };
2551
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
2552
+ const p = 2 * l - q;
2553
+ return rgbToHex(
2554
+ Math.round(hue2rgb(p, q, h + 1 / 3) * 255),
2555
+ Math.round(hue2rgb(p, q, h) * 255),
2556
+ Math.round(hue2rgb(p, q, h - 1 / 3) * 255)
2557
+ );
2558
+ }
2559
+
2560
+ // src/computed/chart-data.ts
2561
+ var ACCENT_KEYS = ["accent1", "accent2", "accent3", "accent4", "accent5", "accent6"];
2562
+ var CHART_TYPE_MAP = [
2563
+ ["barChart", "bar"],
2564
+ ["bar3DChart", "bar"],
2565
+ ["lineChart", "line"],
2566
+ ["line3DChart", "line"],
2567
+ ["pieChart", "pie"],
2568
+ ["pie3DChart", "pie"],
2569
+ ["doughnutChart", "doughnut"],
2570
+ ["scatterChart", "scatter"],
2571
+ ["bubbleChart", "bubble"],
2572
+ ["areaChart", "area"],
2573
+ ["area3DChart", "area"],
2574
+ ["radarChart", "radar"],
2575
+ ["stockChart", "stock"],
2576
+ ["surfaceChart", "surface"],
2577
+ ["surface3DChart", "surface"],
2578
+ ["ofPieChart", "ofPie"]
2579
+ ];
2580
+ function parseComputedChartData(chartXml, colorContext) {
2581
+ const parsed = parseXml(chartXml);
2582
+ const chartSpace = getChild(parsed, "chartSpace");
2583
+ if (chartSpace === void 0) return void 0;
2584
+ const chart = getChild(chartSpace, "chart");
2585
+ if (chart === void 0) return void 0;
2586
+ const plotArea = getChild(chart, "plotArea");
2587
+ if (plotArea === void 0) return void 0;
2588
+ const title = parseChartTitle(getChild(chart, "title"));
2589
+ const parsedChart = parseChartTypeAndData(plotArea, colorContext);
2590
+ if (parsedChart.chartType === void 0) return void 0;
2591
+ return {
2592
+ chartType: parsedChart.chartType,
2593
+ title,
2594
+ series: parsedChart.series,
2595
+ categories: parsedChart.categories,
2596
+ ...parsedChart.barDirection !== void 0 ? { barDirection: parsedChart.barDirection } : {},
2597
+ ...parsedChart.holeSize !== void 0 ? { holeSize: parsedChart.holeSize } : {},
2598
+ ...parsedChart.radarStyle !== void 0 ? { radarStyle: parsedChart.radarStyle } : {},
2599
+ ...parsedChart.ofPieType !== void 0 ? { ofPieType: parsedChart.ofPieType } : {},
2600
+ ...parsedChart.secondPieSize !== void 0 ? { secondPieSize: parsedChart.secondPieSize } : {},
2601
+ ...parsedChart.splitPos !== void 0 ? { splitPos: parsedChart.splitPos } : {},
2602
+ legend: parseLegend(getChild(chart, "legend"))
2603
+ };
2604
+ }
2605
+ function parseChartTypeAndData(plotArea, colorContext) {
2606
+ for (const [xmlTag, chartType] of CHART_TYPE_MAP) {
2607
+ const chartNode = getChild(plotArea, xmlTag);
2608
+ if (chartNode === void 0) continue;
2609
+ const serList = getChildArray(chartNode, "ser");
2610
+ const series = serList.map((ser, index) => parseSeries(ser, chartType, index, colorContext));
2611
+ const categories = extractCategories(serList);
2612
+ const barDirection = chartType === "bar" ? parseBarDirection(getAttr(getChild(chartNode, "barDir"), "val")) : void 0;
2613
+ const holeSize = chartType === "doughnut" ? parseNumberAttribute(getChild(chartNode, "holeSize"), "val", 50) : void 0;
2614
+ const radarStyle = chartType === "radar" ? parseRadarStyle(getAttr(getChild(chartNode, "radarStyle"), "val")) : void 0;
2615
+ const ofPieType = chartType === "ofPie" ? parseOfPieType(getAttr(getChild(chartNode, "ofPieType"), "val")) : void 0;
2616
+ const secondPieSize = chartType === "ofPie" ? parseNumberAttribute(getChild(chartNode, "secondPieSize"), "val", 75) : void 0;
2617
+ const splitPos = chartType === "ofPie" ? parseNumberAttribute(getChild(chartNode, "splitPos"), "val", 2) : void 0;
2618
+ return {
2619
+ chartType,
2620
+ series,
2621
+ categories,
2622
+ ...barDirection !== void 0 ? { barDirection } : {},
2623
+ ...holeSize !== void 0 ? { holeSize } : {},
2624
+ ...radarStyle !== void 0 ? { radarStyle } : {},
2625
+ ...ofPieType !== void 0 ? { ofPieType } : {},
2626
+ ...secondPieSize !== void 0 ? { secondPieSize } : {},
2627
+ ...splitPos !== void 0 ? { splitPos } : {}
2628
+ };
2629
+ }
2630
+ return { series: [], categories: [] };
2631
+ }
2632
+ function parseSeries(ser, chartType, seriesIndex, colorContext) {
2633
+ const name = parseSeriesName(getChild(ser, "tx"));
2634
+ const usesXY = chartType === "scatter" || chartType === "bubble";
2635
+ const values = parseNumericData(usesXY ? getChild(ser, "yVal") : getChild(ser, "val"));
2636
+ const xValues = usesXY ? parseNumericData(getChild(ser, "xVal")) : void 0;
2637
+ const bubbleSizes = chartType === "bubble" ? parseNumericData(getChild(ser, "bubbleSize")) : void 0;
2638
+ const color = resolveSeriesColor(getChild(ser, "spPr"), seriesIndex, colorContext);
2639
+ return {
2640
+ name,
2641
+ values,
2642
+ ...xValues !== void 0 ? { xValues } : {},
2643
+ ...bubbleSizes !== void 0 ? { bubbleSizes } : {},
2644
+ color
2645
+ };
2646
+ }
2647
+ function parseSeriesName(tx) {
2648
+ if (tx === void 0) return null;
2649
+ const strCache = getChild(getChild(tx, "strRef"), "strCache");
2650
+ const cachedValue = firstIndexedPointText(strCache);
2651
+ if (cachedValue !== void 0) return cachedValue;
2652
+ return getChildText(tx, "v") ?? null;
2653
+ }
2654
+ function parseNumericData(valNode) {
2655
+ const numCache = getChild(getChild(valNode, "numRef"), "numCache") ?? getChild(valNode, "numLit");
2656
+ return indexedPointTexts(numCache).map(parseNumericPointValue);
2657
+ }
2658
+ function extractCategories(serList) {
2659
+ for (const ser of serList) {
2660
+ const cat = getChild(ser, "cat");
2661
+ if (cat === void 0) continue;
2662
+ const categoryCache = getChild(getChild(cat, "strRef"), "strCache") ?? getChild(cat, "strLit") ?? getChild(getChild(cat, "numRef"), "numCache") ?? getChild(cat, "numLit");
2663
+ const values = indexedPointTexts(categoryCache).map((value) => String(value ?? ""));
2664
+ if (values.length > 0) return values;
2665
+ const multiCache = getChild(getChild(cat, "multiLvlStrRef"), "multiLvlStrCache") ?? getChild(cat, "multiLvlStrLit");
2666
+ const firstLevel = getChildArray(multiCache, "lvl")[0];
2667
+ const multiValues = indexedPointTexts(firstLevel).map((value) => String(value ?? ""));
2668
+ if (multiValues.length > 0) return multiValues;
2669
+ }
2670
+ return [];
2671
+ }
2672
+ function indexedPointTexts(cache) {
2673
+ return getChildArray(cache, "pt").slice().sort((a, b) => Number(getAttr(a, "idx")) - Number(getAttr(b, "idx"))).map((point) => getChildText(point, "v") ?? "");
2674
+ }
2675
+ function firstIndexedPointText(cache) {
2676
+ return indexedPointTexts(cache)[0];
2677
+ }
2678
+ function parseNumericPointValue(value) {
2679
+ const parsed = Number(value ?? 0);
2680
+ return Number.isFinite(parsed) ? parsed : 0;
2681
+ }
2682
+ function parseNumberAttribute(node, attrName, fallback) {
2683
+ const parsed = Number(getAttr(node, attrName) ?? fallback);
2684
+ return Number.isFinite(parsed) ? parsed : fallback;
2685
+ }
2686
+ function resolveSeriesColor(spPr, seriesIndex, colorContext) {
2687
+ const sourceColor = parseSeriesSourceColor(spPr);
2688
+ if (sourceColor !== void 0) {
2689
+ const resolved = resolveColor(colorContext, sourceColor);
2690
+ if (resolved !== void 0) return resolved;
2691
+ }
2692
+ const accentKey = ACCENT_KEYS[seriesIndex % ACCENT_KEYS.length];
2693
+ return resolveColor(colorContext, { kind: "scheme", scheme: accentKey }) ?? {
2694
+ hex: "#4472c4",
2695
+ alpha: 1
2696
+ };
2697
+ }
2698
+ function parseSeriesSourceColor(spPr) {
2699
+ return parseColorElement(getChild(spPr, "solidFill")) ?? parseColorElement(spPr);
2700
+ }
2701
+ function parseChartTitle(titleNode) {
2702
+ const rich = getChild(getChild(titleNode, "tx"), "rich");
2703
+ if (rich === void 0) return null;
2704
+ const texts = [];
2705
+ for (const paragraph of getChildArray(rich, "p")) {
2706
+ for (const run of getChildArray(paragraph, "r")) {
2707
+ const text = getChildText(run, "t");
2708
+ if (text !== void 0) texts.push(text);
2709
+ }
2710
+ }
2711
+ return texts.length > 0 ? texts.join("") : null;
2712
+ }
2713
+ function parseLegend(legendNode) {
2714
+ if (legendNode === void 0) return null;
2715
+ return { position: parseLegendPosition(getAttr(getChild(legendNode, "legendPos"), "val")) };
2716
+ }
2717
+ function parseBarDirection(value) {
2718
+ return value === "bar" ? "bar" : "col";
2719
+ }
2720
+ function parseRadarStyle(value) {
2721
+ if (value === "marker" || value === "filled") return value;
2722
+ return "standard";
2723
+ }
2724
+ function parseOfPieType(value) {
2725
+ return value === "bar" ? "bar" : "pie";
2726
+ }
2727
+ function parseLegendPosition(value) {
2728
+ if (value === "b" || value === "t" || value === "l" || value === "tr") return value;
2729
+ return "r";
2730
+ }
2731
+
2732
+ // src/computed/placeholders.ts
2733
+ function findPlaceholderMatch(context, shape) {
2734
+ if (shape.placeholder === void 0) return void 0;
2735
+ const type = shape.placeholder.type ?? "body";
2736
+ const index = shape.placeholder.index;
2737
+ const layout = findMatchingPlaceholder(type, index, context.layoutShapes);
2738
+ const master = findMatchingPlaceholder(type, index, context.masterShapes);
2739
+ if (layout === void 0 && master === void 0) return void 0;
2740
+ return {
2741
+ ...layout !== void 0 ? { layout } : {},
2742
+ ...master !== void 0 ? { master } : {}
2743
+ };
2744
+ }
2745
+ function findMatchingPlaceholder(type, index, shapes) {
2746
+ const placeholders = shapes.filter(
2747
+ (shape) => shape.kind === "shape" && shape.placeholder !== void 0
2748
+ );
2749
+ if (index !== void 0) {
2750
+ const byIndexWithTransform = placeholders.find(
2751
+ (shape) => shape.placeholder?.index === index && shape.transform !== void 0
2752
+ );
2753
+ if (byIndexWithTransform !== void 0) return byIndexWithTransform;
2754
+ const byIndex = placeholders.find((shape) => shape.placeholder?.index === index);
2755
+ if (byIndex !== void 0) return byIndex;
2756
+ }
2757
+ const byTypeWithTransform = placeholders.find(
2758
+ (shape) => (shape.placeholder?.type ?? "body") === type && shape.transform !== void 0
2759
+ );
2760
+ if (byTypeWithTransform !== void 0) return byTypeWithTransform;
2761
+ const fallbackType = getPlaceholderFallbackType(type);
2762
+ if (fallbackType !== void 0) {
2763
+ const byFallbackWithTransform = placeholders.find(
2764
+ (shape) => (shape.placeholder?.type ?? "body") === fallbackType && shape.transform !== void 0
2765
+ );
2766
+ if (byFallbackWithTransform !== void 0) return byFallbackWithTransform;
2767
+ }
2768
+ const byType = placeholders.find((shape) => (shape.placeholder?.type ?? "body") === type);
2769
+ if (byType !== void 0) return byType;
2770
+ if (fallbackType !== void 0) {
2771
+ return placeholders.find((shape) => (shape.placeholder?.type ?? "body") === fallbackType);
2772
+ }
2773
+ return void 0;
2774
+ }
2775
+ function getPlaceholderFallbackType(type) {
2776
+ if (type === "ctrTitle") return "title";
2777
+ if (type === "subTitle") return "body";
2778
+ return void 0;
2779
+ }
2780
+
2781
+ // src/source/package-paths.ts
2782
+ var RELS_SUFFIX = ".rels";
2783
+ var RELS_MARKER = "_rels/";
2784
+ var ABSOLUTE_URI_PATTERN = /^[a-zA-Z][a-zA-Z0-9+.-]*:/;
2785
+ function isRelationshipPart(path) {
2786
+ return path.endsWith(RELS_SUFFIX) && path.includes(RELS_MARKER);
2787
+ }
2788
+ function relationshipsPartPath(sourcePartPath) {
2789
+ if (sourcePartPath === "") return "_rels/.rels";
2790
+ const slash = sourcePartPath.lastIndexOf("/");
2791
+ const dir = slash === -1 ? "" : sourcePartPath.slice(0, slash + 1);
2792
+ const file = slash === -1 ? sourcePartPath : sourcePartPath.slice(slash + 1);
2793
+ return `${dir}_rels/${file}.rels`;
2794
+ }
2795
+ function relationshipsSourcePartPath(relsPath) {
2796
+ const idx = relsPath.lastIndexOf(RELS_MARKER);
2797
+ const dir = relsPath.slice(0, idx);
2798
+ const file = relsPath.slice(idx + RELS_MARKER.length);
2799
+ const base = file.endsWith(RELS_SUFFIX) ? file.slice(0, -RELS_SUFFIX.length) : file;
2800
+ return asPartPath(dir + base);
2801
+ }
2802
+ function resolveRelationshipTarget(sourcePartPath, target) {
2803
+ if (ABSOLUTE_URI_PATTERN.test(target)) return target;
2804
+ const combined = target.startsWith("/") ? target.slice(1) : joinPackageRelativeTarget(sourcePartPath, target);
2805
+ return normalizePackagePath(combined);
2806
+ }
2807
+ function resolveInternalRelationshipTarget(sourcePartPath, relationship) {
2808
+ if (relationship.targetMode === "External") return void 0;
2809
+ return asPartPath(resolveRelationshipTarget(sourcePartPath, relationship.target));
2810
+ }
2811
+ function parseRelationshipTargetMode(value) {
2812
+ if (value === "Internal" || value === "External") return value;
2813
+ return void 0;
2814
+ }
2815
+ function joinPackageRelativeTarget(sourcePartPath, target) {
2816
+ const slash = sourcePartPath.lastIndexOf("/");
2817
+ const baseDir = slash === -1 ? "" : sourcePartPath.slice(0, slash);
2818
+ return baseDir === "" ? target : `${baseDir}/${target}`;
2819
+ }
2820
+ function normalizePackagePath(path) {
2821
+ const segments = [];
2822
+ for (const segment of path.split("/")) {
2823
+ if (segment === "" || segment === ".") continue;
2824
+ if (segment === "..") {
2825
+ segments.pop();
2826
+ continue;
2827
+ }
2828
+ segments.push(segment);
2829
+ }
2830
+ return segments.join("/");
2831
+ }
2832
+
2833
+ // src/computed/relationships.ts
2834
+ function resolveComputedRelationships(source, sourcePartPath) {
2835
+ const rels = source.packageGraph.relationships.find((entry) => entry.sourcePartPath === sourcePartPath)?.relationships ?? [];
2836
+ return rels.map((relationship) => {
2837
+ const external = relationship.targetMode === "External";
2838
+ const target = external ? relationship.target : resolveRelationshipTarget(sourcePartPath, relationship.target);
2839
+ const targetPartPath = external ? void 0 : asPartPath(target);
2840
+ const media = targetPartPath !== void 0 ? findMedia(source.packageGraph.media, targetPartPath) : void 0;
2841
+ return {
2842
+ id: relationship.id,
2843
+ type: relationship.type,
2844
+ source: relationship,
2845
+ target,
2846
+ ...relationship.targetMode !== void 0 ? { targetMode: relationship.targetMode } : {},
2847
+ ...targetPartPath !== void 0 ? { targetPartPath } : {},
2848
+ ...media !== void 0 ? { media } : {}
2849
+ };
2850
+ });
2851
+ }
2852
+ function findMedia(media, partPath) {
2853
+ return media.find((part) => part.partPath === partPath);
2854
+ }
2855
+
2856
+ // src/computed/create-computed-view.ts
2857
+ var IMAGE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
2858
+ var CHART_REL_TYPES = /* @__PURE__ */ new Set([
2859
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart",
2860
+ "http://purl.oclc.org/ooxml/officeDocument/relationships/chart"
2861
+ ]);
2862
+ var DIAGRAM_DATA_REL_TYPES = /* @__PURE__ */ new Set([
2863
+ "http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData",
2864
+ "http://purl.oclc.org/ooxml/officeDocument/relationships/diagramData"
2865
+ ]);
2866
+ var DIAGRAM_DRAWING_REL_TYPES = /* @__PURE__ */ new Set([
2867
+ "http://schemas.microsoft.com/office/2007/relationships/diagramDrawing",
2868
+ "http://purl.oclc.org/ooxml/officeDocument/relationships/diagramDrawing"
2869
+ ]);
2870
+ var textDecoder = new TextDecoder();
2871
+ var DEFAULT_TABLE_STYLE_BORDERS = {
2872
+ top: {
2873
+ width: asEmu(12700),
2874
+ fill: { kind: "solid", color: { kind: "srgb", hex: "000000" } }
2875
+ },
2876
+ bottom: {
2877
+ width: asEmu(12700),
2878
+ fill: { kind: "solid", color: { kind: "srgb", hex: "000000" } }
2879
+ },
2880
+ left: {
2881
+ width: asEmu(12700),
2882
+ fill: { kind: "solid", color: { kind: "srgb", hex: "000000" } }
2883
+ },
2884
+ right: {
2885
+ width: asEmu(12700),
2886
+ fill: { kind: "solid", color: { kind: "srgb", hex: "000000" } }
2887
+ }
2888
+ };
2889
+ function createComputedView(source, options = {}) {
2890
+ const slidesByPath = new Map(source.slides.map((slide) => [slide.partPath, slide]));
2891
+ const selectedSlideNumbers = options.slides !== void 0 ? new Set(options.slides) : void 0;
2892
+ const slides = [];
2893
+ source.presentation.slidePartPaths.forEach((partPath, index) => {
2894
+ const slideNumber = index + 1;
2895
+ if (selectedSlideNumbers !== void 0 && !selectedSlideNumbers.has(slideNumber)) return;
2896
+ const slide = slidesByPath.get(partPath);
2897
+ if (slide === void 0) return;
2898
+ slides.push(computeSlide(source, slide, slideNumber, options));
2899
+ });
2900
+ return {
2901
+ ...source.presentation.slideSize !== void 0 ? { slideSize: { ...source.presentation.slideSize } } : {},
2902
+ slides
2903
+ };
2904
+ }
2905
+ function computeSlide(source, slide, slideNumber, options) {
2906
+ const layout = source.slideLayouts.find(
2907
+ (candidate) => candidate.partPath === slide.layoutPartPath
2908
+ );
2909
+ const master = layout !== void 0 ? source.slideMasters.find((candidate) => candidate.partPath === layout.masterPartPath) : void 0;
2910
+ const theme = master?.themePartPath !== void 0 ? source.themes.find((candidate) => candidate.partPath === master.themePartPath) : void 0;
2911
+ const colorMap = buildEffectiveColorMap(
2912
+ master?.colorMap,
2913
+ layout?.colorMapOverride,
2914
+ slide.colorMapOverride
2915
+ );
2916
+ const relationships = resolveComputedRelationships(source, slide.partPath);
2917
+ const context = { source, layout, master, theme, colorMap, relationships };
2918
+ const colorScheme = buildComputedColorScheme(context);
2919
+ const layoutShowMasterShapes = layout?.showMasterShapes ?? true;
2920
+ const showMasterShapes = slide.showMasterShapes ?? true;
2921
+ const includeMaster = options.applyMasterVisibility === false ? true : showMasterShapes && layoutShowMasterShapes;
2922
+ return {
2923
+ slideNumber,
2924
+ partPath: slide.partPath,
2925
+ ...layout !== void 0 ? { layoutPartPath: layout.partPath } : {},
2926
+ ...master !== void 0 ? { masterPartPath: master.partPath } : {},
2927
+ ...theme?.partPath !== void 0 ? { themePartPath: theme.partPath } : {},
2928
+ ...source.presentation.slideSize !== void 0 ? { slideSize: { ...source.presentation.slideSize } } : {},
2929
+ relationships,
2930
+ colorMap,
2931
+ colorScheme,
2932
+ ...computeBackground(context, slide, layout, master) ?? {},
2933
+ showMasterShapes,
2934
+ layoutShowMasterShapes,
2935
+ elements: [
2936
+ ...includeMaster && master !== void 0 ? computeTemplateElements(context, master.shapes, "master", master.partPath) : [],
2937
+ ...layout !== void 0 ? computeTemplateElements(context, layout.shapes, "layout", layout.partPath) : [],
2938
+ ...computeSlideElements(context, slide.shapes, slide.partPath)
2939
+ ]
2940
+ };
2941
+ }
2942
+ function computeBackground(context, slide, layout, master) {
2943
+ const picked = slide.background !== void 0 ? { sourceLayer: "slide", partPath: slide.partPath, background: slide.background } : layout?.background !== void 0 ? {
2944
+ sourceLayer: "layout",
2945
+ partPath: layout.partPath,
2946
+ background: layout.background
2947
+ } : master?.background !== void 0 ? {
2948
+ sourceLayer: "master",
2949
+ partPath: master.partPath,
2950
+ background: master.background
2951
+ } : void 0;
2952
+ if (picked === void 0) return void 0;
2953
+ const { background, sourceLayer } = picked;
2954
+ switch (background.kind) {
2955
+ case "fill":
2956
+ return {
2957
+ background: {
2958
+ kind: "fill",
2959
+ source: background,
2960
+ fill: computeFill(context, background.fill, picked.partPath),
2961
+ sourceLayer
2962
+ }
2963
+ };
2964
+ case "styleReference": {
2965
+ const color = resolveColor(context, background.color);
2966
+ return {
2967
+ background: {
2968
+ kind: "styleReference",
2969
+ source: background,
2970
+ index: background.index,
2971
+ ...color !== void 0 ? { color } : {},
2972
+ sourceLayer
2973
+ }
2974
+ };
2975
+ }
2976
+ case "raw":
2977
+ return { background: { kind: "raw", source: background, sourceLayer } };
2978
+ }
2979
+ }
2980
+ function computeTemplateElements(context, elements, layer, partPath) {
2981
+ return elements.filter((element) => !(element.kind === "shape" && element.placeholder !== void 0)).map((element) => computeElement(context, element, layer, partPath));
2982
+ }
2983
+ function computeSlideElements(context, elements, partPath) {
2984
+ return elements.filter((element) => !(element.kind === "shape" && isEmptyPlaceholder(element))).map((element) => computeElement(context, element, "slide", partPath));
2985
+ }
2986
+ function computeElement(context, element, layer, partPath) {
2987
+ switch (element.kind) {
2988
+ case "shape":
2989
+ return computeShapeElement(context, element, layer, partPath);
2990
+ case "connector":
2991
+ return computeConnectorElement(context, element, layer, partPath);
2992
+ case "group":
2993
+ return computeGroupElement(context, element, layer, partPath);
2994
+ case "image":
2995
+ return computeImageElement(context, element, layer, partPath);
2996
+ case "table":
2997
+ return computeTableElement(context, element, layer, partPath);
2998
+ case "chart":
2999
+ return computeChartElement(context, element, layer, partPath);
3000
+ case "smartArt":
3001
+ return computeSmartArtElement(context, element, layer, partPath);
3002
+ case "raw":
3003
+ return { kind: "raw", sourceLayer: layer, sourcePartPath: partPath, sourceNode: element };
3004
+ }
3005
+ }
3006
+ function computeConnectorElement(context, connector, layer, partPath) {
3007
+ const effects = connector.effects !== void 0 ? computeEffectList(context, connector.effects) : connector.style?.effectRef !== void 0 ? resolveEffectReference(context, connector.style.effectRef) : void 0;
3008
+ return {
3009
+ kind: "connector",
3010
+ sourceLayer: layer,
3011
+ sourcePartPath: partPath,
3012
+ sourceNode: connector,
3013
+ ...connector.transform !== void 0 ? { transform: connector.transform } : {},
3014
+ ...connector.geometry !== void 0 ? { geometry: connector.geometry } : {},
3015
+ ...connector.outline !== void 0 ? { outline: computeOutline(context, connector.outline, partPath) } : connector.style?.lineRef !== void 0 ? { outline: resolveLineReference(context, connector.style.lineRef, partPath) } : {},
3016
+ ...effects !== void 0 ? { effects } : {}
3017
+ };
3018
+ }
3019
+ function computeGroupElement(context, group, layer, partPath) {
3020
+ const fill = group.fill !== void 0 ? computeFill(context, group.fill, partPath) : void 0;
3021
+ const effects = group.effects !== void 0 ? computeEffectList(context, group.effects) : void 0;
3022
+ const childContext = fill !== void 0 ? { ...context, groupFill: fill } : context;
3023
+ return {
3024
+ kind: "group",
3025
+ sourceLayer: layer,
3026
+ sourcePartPath: partPath,
3027
+ sourceNode: group,
3028
+ ...group.transform !== void 0 ? { transform: group.transform } : {},
3029
+ ...group.childTransform !== void 0 ? { childTransform: group.childTransform } : {},
3030
+ ...fill !== void 0 ? { fill } : {},
3031
+ ...effects !== void 0 ? { effects } : {},
3032
+ children: group.children.map((child) => computeElement(childContext, child, layer, partPath))
3033
+ };
3034
+ }
3035
+ function computeShapeElement(context, shape, layer, partPath) {
3036
+ const match = layer === "slide" ? findPlaceholderMatch(
3037
+ {
3038
+ layoutShapes: context.layout?.shapes ?? [],
3039
+ masterShapes: context.master?.shapes ?? []
3040
+ },
3041
+ shape
3042
+ ) : void 0;
3043
+ const placeholderType = shape.placeholder !== void 0 ? shape.placeholder.type ?? "body" : void 0;
3044
+ const transform = firstDefined(
3045
+ shape.transform,
3046
+ match?.layout?.transform,
3047
+ match?.master?.transform
3048
+ );
3049
+ const geometry = firstDefined(shape.geometry, match?.layout?.geometry, match?.master?.geometry);
3050
+ const effects = shape.effects !== void 0 ? computeEffectList(context, shape.effects) : shape.style?.effectRef !== void 0 ? resolveEffectReference(context, shape.style.effectRef) : void 0;
3051
+ return {
3052
+ kind: "shape",
3053
+ sourceLayer: layer,
3054
+ sourcePartPath: partPath,
3055
+ sourceNode: shape,
3056
+ ...transform !== void 0 ? { transform } : {},
3057
+ ...geometry !== void 0 ? { geometry } : {},
3058
+ ...shape.fill !== void 0 ? { fill: computeFill(context, shape.fill, partPath) } : shape.style?.fillRef !== void 0 ? { fill: resolveFillReference(context, shape.style.fillRef, partPath) } : {},
3059
+ ...shape.outline !== void 0 ? { outline: computeOutline(context, shape.outline, partPath) } : shape.style?.lineRef !== void 0 ? { outline: resolveLineReference(context, shape.style.lineRef, partPath) } : {},
3060
+ ...effects !== void 0 ? { effects } : {},
3061
+ ...shape.textBody !== void 0 ? {
3062
+ textBody: computeTextBody(
3063
+ context,
3064
+ shape.textBody,
3065
+ [match?.layout?.textBody, match?.master?.textBody],
3066
+ placeholderType
3067
+ )
3068
+ } : {},
3069
+ ...match !== void 0 ? { placeholderMatch: match } : {}
3070
+ };
3071
+ }
3072
+ function computeImageElement(context, image, layer, partPath) {
3073
+ const relationship = resolveComputedRelationships(context.source, partPath).find(
3074
+ (rel) => rel.id === image.blipRelationshipId && rel.type === IMAGE_REL_TYPE
3075
+ );
3076
+ const effects = image.effects !== void 0 ? computeEffectList(context, image.effects) : void 0;
3077
+ const blipEffects = image.blipEffects !== void 0 ? computeBlipEffects(context, image.blipEffects) : void 0;
3078
+ return {
3079
+ kind: "image",
3080
+ sourceLayer: layer,
3081
+ sourcePartPath: partPath,
3082
+ sourceNode: image,
3083
+ ...image.transform !== void 0 ? { transform: image.transform } : {},
3084
+ ...relationship !== void 0 ? { relationship } : {},
3085
+ ...relationship?.media !== void 0 ? { media: relationship.media } : {},
3086
+ ...effects !== void 0 ? { effects } : {},
3087
+ ...blipEffects !== void 0 ? { blipEffects } : {}
3088
+ };
3089
+ }
3090
+ function computeTableElement(context, table, layer, partPath) {
3091
+ return {
3092
+ kind: "table",
3093
+ sourceLayer: layer,
3094
+ sourcePartPath: partPath,
3095
+ sourceNode: table,
3096
+ ...table.transform !== void 0 ? { transform: table.transform } : {},
3097
+ table: {
3098
+ columns: table.table.columns.map((column) => ({ ...column })),
3099
+ rows: table.table.rows.map((row) => computeTableRow(context, table, row, partPath))
3100
+ }
3101
+ };
3102
+ }
3103
+ function computeChartElement(context, chart, layer, partPath) {
3104
+ const relationship = context.relationships.find(
3105
+ (rel) => rel.id === chart.chartRelationshipId && CHART_REL_TYPES.has(rel.type)
3106
+ );
3107
+ const chartXml = relationship?.targetPartPath !== void 0 ? readRawPackageText(context.source, relationship.targetPartPath) : void 0;
3108
+ const chartData = chartXml !== void 0 ? parseComputedChartData(chartXml, context) : void 0;
3109
+ return {
3110
+ kind: "chart",
3111
+ sourceLayer: layer,
3112
+ sourcePartPath: partPath,
3113
+ sourceNode: chart,
3114
+ ...chart.transform !== void 0 ? { transform: chart.transform } : {},
3115
+ ...relationship !== void 0 ? { relationship } : {},
3116
+ ...chartXml !== void 0 ? { chartXml } : {},
3117
+ ...chartData !== void 0 ? { chartData } : {}
3118
+ };
3119
+ }
3120
+ function computeSmartArtElement(context, smartArt, layer, partPath) {
3121
+ const dataRelationship = context.relationships.find(
3122
+ (rel) => rel.id === smartArt.dataRelationshipId && DIAGRAM_DATA_REL_TYPES.has(rel.type)
3123
+ );
3124
+ const dataRelationships = dataRelationship?.targetPartPath !== void 0 ? resolveComputedRelationships(context.source, dataRelationship.targetPartPath) : [];
3125
+ const drawingRelationship = dataRelationships.find(
3126
+ (rel) => DIAGRAM_DRAWING_REL_TYPES.has(rel.type)
3127
+ );
3128
+ const drawingPartPath = drawingRelationship?.targetPartPath;
3129
+ const drawingXml = drawingPartPath !== void 0 ? readRawPackageText(context.source, drawingPartPath) : void 0;
3130
+ const drawingRelationships = drawingPartPath !== void 0 ? resolveComputedRelationships(context.source, drawingPartPath) : [];
3131
+ const diagramDrawing = drawingPartPath !== void 0 && drawingXml !== void 0 ? computeDiagramDrawing(context, drawingPartPath, drawingXml, drawingRelationships, layer) : void 0;
3132
+ return {
3133
+ kind: "smartArt",
3134
+ sourceLayer: layer,
3135
+ sourcePartPath: partPath,
3136
+ sourceNode: smartArt,
3137
+ ...smartArt.transform !== void 0 ? { transform: smartArt.transform } : {},
3138
+ ...dataRelationship !== void 0 ? { dataRelationship } : {},
3139
+ ...drawingRelationship !== void 0 ? { drawingRelationship } : {},
3140
+ ...drawingPartPath !== void 0 ? { drawingPartPath } : {},
3141
+ ...drawingXml !== void 0 ? { drawingXml } : {},
3142
+ drawingRelationships,
3143
+ media: context.source.packageGraph.media,
3144
+ ...diagramDrawing !== void 0 ? { diagramDrawing } : {}
3145
+ };
3146
+ }
3147
+ function computeDiagramDrawing(context, drawingPartPath, drawingXml, drawingRelationships, layer) {
3148
+ const rawPart = context.source.packageGraph.rawParts?.find(
3149
+ (part) => part.partPath === drawingPartPath
3150
+ );
3151
+ const parsed = parseXml(drawingXml);
3152
+ const drawing = getChild(parsed, "drawing");
3153
+ const spTree = getChild(drawing, "spTree");
3154
+ const diagnostics = [];
3155
+ if (spTree === void 0) {
3156
+ diagnostics.push({
3157
+ severity: "warning",
3158
+ code: "diagram-drawing-shape-tree-missing",
3159
+ message: `diagram drawing part '${drawingPartPath}' has no shape tree`,
3160
+ sourcePartPath: drawingPartPath
3161
+ });
3162
+ }
3163
+ const orderedSpTree = spTree !== void 0 ? navigateOrdered(parseXmlOrdered(drawingXml), ["drawing", "spTree"]) : void 0;
3164
+ const sourceChildren = spTree !== void 0 ? parseShapeTree(
3165
+ spTree,
3166
+ drawingPartPath,
3167
+ createSidecarIdFactory(drawingPartPath),
3168
+ orderedSpTree
3169
+ ) : [];
3170
+ const diagramContext = {
3171
+ ...context,
3172
+ relationships: drawingRelationships
3173
+ };
3174
+ return {
3175
+ sourcePartPath: drawingPartPath,
3176
+ rawXml: drawingXml,
3177
+ ...rawPart !== void 0 ? { rawPart } : {},
3178
+ rawHandle: { partPath: drawingPartPath },
3179
+ relationships: drawingRelationships,
3180
+ media: context.source.packageGraph.media,
3181
+ ...spTree !== void 0 ? { childTransform: parseDiagramChildTransform(spTree) } : {},
3182
+ children: sourceChildren.map(
3183
+ (child) => computeElement(diagramContext, child, layer, drawingPartPath)
3184
+ ),
3185
+ diagnostics
3186
+ };
3187
+ }
3188
+ function parseDiagramChildTransform(spTree) {
3189
+ const groupProperties = getChild(spTree, "grpSpPr");
3190
+ const fallback = parseTransform(groupProperties);
3191
+ const xfrm = getChild(groupProperties, "xfrm");
3192
+ const childOff = getChild(xfrm, "chOff");
3193
+ const childExt = getChild(xfrm, "chExt");
3194
+ const offsetX = numericAttr3(childOff, "x") ?? 0;
3195
+ const offsetY = numericAttr3(childOff, "y") ?? 0;
3196
+ const width = numericAttr3(childExt, "cx") ?? fallback?.width;
3197
+ const height = numericAttr3(childExt, "cy") ?? fallback?.height;
3198
+ if (width === void 0 || height === void 0) return void 0;
3199
+ return {
3200
+ offsetX: asEmu(offsetX),
3201
+ offsetY: asEmu(offsetY),
3202
+ width: asEmu(width),
3203
+ height: asEmu(height)
3204
+ };
3205
+ }
3206
+ function computeTableRow(context, table, row, partPath) {
3207
+ return {
3208
+ source: row,
3209
+ height: row.height,
3210
+ cells: row.cells.map((cell) => computeTableCell(context, table, cell, partPath))
3211
+ };
3212
+ }
3213
+ function computeTableCell(context, table, cell, partPath) {
3214
+ const borders = cell.borders !== void 0 ? computeCellBorders(context, cell.borders, partPath) : table.table.tableStyleId !== void 0 ? computeCellBorders(context, DEFAULT_TABLE_STYLE_BORDERS, partPath) : void 0;
3215
+ return {
3216
+ source: cell,
3217
+ ...cell.textBody !== void 0 ? { textBody: computeTextBody(context, cell.textBody, [], void 0, false) } : {},
3218
+ ...cell.fill !== void 0 ? { fill: computeFill(context, cell.fill, partPath) } : {},
3219
+ ...borders !== void 0 ? { borders } : {},
3220
+ gridSpan: cell.gridSpan,
3221
+ rowSpan: cell.rowSpan,
3222
+ hMerge: cell.hMerge,
3223
+ vMerge: cell.vMerge
3224
+ };
3225
+ }
3226
+ function computeCellBorders(context, borders, partPath) {
3227
+ const computed = {
3228
+ ...borders.top !== void 0 ? { top: computeOutline(context, borders.top, partPath) } : {},
3229
+ ...borders.bottom !== void 0 ? { bottom: computeOutline(context, borders.bottom, partPath) } : {},
3230
+ ...borders.left !== void 0 ? { left: computeOutline(context, borders.left, partPath) } : {},
3231
+ ...borders.right !== void 0 ? { right: computeOutline(context, borders.right, partPath) } : {}
3232
+ };
3233
+ return Object.keys(computed).length > 0 ? computed : void 0;
3234
+ }
3235
+ function computeFill(context, fill, partPath) {
3236
+ switch (fill.kind) {
3237
+ case "none":
3238
+ return { kind: "none", source: fill };
3239
+ case "raw":
3240
+ if (localName(fill.raw.node.name) === "grpFill" && context.groupFill !== void 0) {
3241
+ return context.groupFill;
3242
+ }
3243
+ return { kind: "raw", source: fill };
3244
+ case "gradient":
3245
+ return {
3246
+ kind: "gradient",
3247
+ source: fill,
3248
+ stops: fill.stops.map((stop) => ({
3249
+ position: stop.position,
3250
+ color: resolveColor(context, stop.color) ?? { hex: "#000000", alpha: 1 }
3251
+ })),
3252
+ gradientType: fill.gradientType,
3253
+ ...fill.gradientType === "linear" ? { angle: Number(fill.angle) / 6e4 } : {},
3254
+ ...fill.gradientType === "radial" ? { centerX: fill.centerX, centerY: fill.centerY } : {}
3255
+ };
3256
+ case "pattern":
3257
+ return {
3258
+ kind: "pattern",
3259
+ source: fill,
3260
+ preset: fill.preset,
3261
+ foregroundColor: resolveColor(context, fill.foregroundColor) ?? {
3262
+ hex: "#000000",
3263
+ alpha: 1
3264
+ },
3265
+ backgroundColor: resolveColor(context, fill.backgroundColor) ?? {
3266
+ hex: "#ffffff",
3267
+ alpha: 1
3268
+ }
3269
+ };
3270
+ case "image": {
3271
+ const relationship = resolveComputedRelationships(context.source, partPath).find(
3272
+ (rel) => rel.id === fill.blipRelationshipId && rel.type === IMAGE_REL_TYPE
3273
+ );
3274
+ return {
3275
+ kind: "image",
3276
+ source: fill,
3277
+ ...relationship !== void 0 ? { relationship } : {},
3278
+ ...relationship?.media !== void 0 ? { media: relationship.media } : {},
3279
+ ...fill.tile !== void 0 ? { tile: fill.tile } : {}
3280
+ };
3281
+ }
3282
+ case "solid":
3283
+ return {
3284
+ kind: "solid",
3285
+ source: fill,
3286
+ color: resolveColor(context, fill.color) ?? { hex: "#000000", alpha: 1 }
3287
+ };
3288
+ }
3289
+ }
3290
+ function computeOutline(context, outline, partPath) {
3291
+ return {
3292
+ source: outline,
3293
+ ...outline.width !== void 0 ? { width: outline.width } : {},
3294
+ ...outline.fill !== void 0 ? { fill: computeFill(context, outline.fill, partPath) } : {}
3295
+ };
3296
+ }
3297
+ function resolveFillReference(context, ref, partPath) {
3298
+ if (ref.index === 0) return void 0;
3299
+ const list = ref.index >= 1e3 ? context.theme?.formatScheme?.backgroundFillStyles : context.theme?.formatScheme?.fillStyles;
3300
+ const arrayIndex = ref.index >= 1e3 ? ref.index - 1001 : ref.index - 1;
3301
+ const template = list?.[arrayIndex];
3302
+ if (template === void 0) return void 0;
3303
+ const computed = computeFill(context, template, context.theme?.partPath ?? partPath);
3304
+ const overrideColor = ref.color !== void 0 ? resolveColor(context, ref.color) : void 0;
3305
+ if (overrideColor === void 0) return computed;
3306
+ if (computed.kind === "solid") {
3307
+ return { ...computed, color: overrideColor };
3308
+ }
3309
+ if (computed.kind === "gradient") {
3310
+ return {
3311
+ ...computed,
3312
+ stops: computed.stops.map((stop) => ({ ...stop, color: overrideColor }))
3313
+ };
3314
+ }
3315
+ return computed;
3316
+ }
3317
+ function resolveLineReference(context, ref, partPath) {
3318
+ if (ref.index === 0) return void 0;
3319
+ const template = context.theme?.formatScheme?.lineStyles[ref.index - 1];
3320
+ if (template === void 0) return void 0;
3321
+ const computed = computeOutline(context, template, context.theme?.partPath ?? partPath);
3322
+ const overrideSourceColor = ref.color;
3323
+ if (overrideSourceColor === void 0) return computed;
3324
+ const overrideColor = resolveColor(context, overrideSourceColor);
3325
+ if (overrideColor === void 0) return computed;
3326
+ return {
3327
+ ...computed,
3328
+ fill: {
3329
+ kind: "solid",
3330
+ source: { kind: "solid", color: overrideSourceColor },
3331
+ color: overrideColor
3332
+ }
3333
+ };
3334
+ }
3335
+ function resolveEffectReference(context, ref) {
3336
+ const template = context.theme?.formatScheme?.effectStyles[ref.index];
3337
+ return template !== void 0 ? computeEffectList(context, template) : void 0;
3338
+ }
3339
+ function computeEffectList(context, source) {
3340
+ const outerShadowColor = source.outerShadow !== void 0 ? resolveColor(context, source.outerShadow.color) : void 0;
3341
+ const innerShadowColor = source.innerShadow !== void 0 ? resolveColor(context, source.innerShadow.color) : void 0;
3342
+ const glowColor = source.glow !== void 0 ? resolveColor(context, source.glow.color) : void 0;
3343
+ const computed = {
3344
+ source,
3345
+ ...source.outerShadow !== void 0 && outerShadowColor !== void 0 ? {
3346
+ outerShadow: {
3347
+ blurRadius: source.outerShadow.blurRadius,
3348
+ distance: source.outerShadow.distance,
3349
+ direction: Number(source.outerShadow.direction) / 6e4,
3350
+ color: outerShadowColor,
3351
+ alignment: source.outerShadow.alignment,
3352
+ rotateWithShape: source.outerShadow.rotateWithShape
3353
+ }
3354
+ } : {},
3355
+ ...source.innerShadow !== void 0 && innerShadowColor !== void 0 ? {
3356
+ innerShadow: {
3357
+ blurRadius: source.innerShadow.blurRadius,
3358
+ distance: source.innerShadow.distance,
3359
+ direction: Number(source.innerShadow.direction) / 6e4,
3360
+ color: innerShadowColor
3361
+ }
3362
+ } : {},
3363
+ ...source.glow !== void 0 && glowColor !== void 0 ? {
3364
+ glow: {
3365
+ radius: source.glow.radius,
3366
+ color: glowColor
3367
+ }
3368
+ } : {},
3369
+ ...source.softEdge !== void 0 ? { softEdge: source.softEdge } : {}
3370
+ };
3371
+ return computed.outerShadow !== void 0 || computed.innerShadow !== void 0 || computed.glow !== void 0 || computed.softEdge !== void 0 ? computed : void 0;
3372
+ }
3373
+ function computeBlipEffects(context, source) {
3374
+ const duotoneColor1 = source.duotone !== void 0 ? resolveColor(context, source.duotone.color1) : void 0;
3375
+ const duotoneColor2 = source.duotone !== void 0 ? resolveColor(context, source.duotone.color2) : void 0;
3376
+ const clrChangeFrom = source.clrChange !== void 0 ? resolveColor(context, source.clrChange.from) : void 0;
3377
+ const clrChangeTo = source.clrChange !== void 0 ? resolveColor(context, source.clrChange.to) : void 0;
3378
+ const computed = {
3379
+ source,
3380
+ grayscale: source.grayscale,
3381
+ ...source.biLevel !== void 0 ? { biLevel: source.biLevel } : {},
3382
+ ...source.blur !== void 0 ? { blur: source.blur } : {},
3383
+ ...source.lum !== void 0 ? { lum: source.lum } : {},
3384
+ ...duotoneColor1 !== void 0 && duotoneColor2 !== void 0 ? { duotone: { color1: duotoneColor1, color2: duotoneColor2 } } : {},
3385
+ ...clrChangeFrom !== void 0 && clrChangeTo !== void 0 ? { clrChange: { from: clrChangeFrom, to: clrChangeTo } } : {}
3386
+ };
3387
+ return computed.grayscale || computed.biLevel !== void 0 || computed.blur !== void 0 || computed.lum !== void 0 || computed.duotone !== void 0 || computed.clrChange !== void 0 ? computed : void 0;
3388
+ }
3389
+ function computeTextBody(context, textBody, inheritedBodies = [], placeholderType, includeInheritedStyleChain = true) {
3390
+ const styleChain = buildTextStyleChain(
3391
+ context,
3392
+ textBody,
3393
+ inheritedBodies,
3394
+ placeholderType,
3395
+ includeInheritedStyleChain
3396
+ );
3397
+ const properties = mergeTextBodyProperties(void 0, textBody.properties);
3398
+ return {
3399
+ ...properties !== void 0 ? { properties } : {},
3400
+ paragraphs: textBody.paragraphs.map(
3401
+ (paragraph) => computeParagraph(context, paragraph, styleChain)
3402
+ )
3403
+ };
3404
+ }
3405
+ function mergeTextBodyProperties(inherited, local) {
3406
+ const merged = { ...inherited, ...local };
3407
+ if (Object.keys(merged).length === 0) return void 0;
3408
+ if (merged.autoFit === "normAutofit") {
3409
+ return {
3410
+ ...merged,
3411
+ fontScale: merged.fontScale ?? 1,
3412
+ lnSpcReduction: merged.lnSpcReduction ?? 0
3413
+ };
3414
+ }
3415
+ if (merged.autoFit === "spAutofit" || merged.autoFit === "noAutofit") {
3416
+ return {
3417
+ ...merged,
3418
+ fontScale: 1,
3419
+ lnSpcReduction: 0
3420
+ };
3421
+ }
3422
+ return merged;
3423
+ }
3424
+ function computeParagraph(context, paragraph, styleChain) {
3425
+ const level = paragraph.properties?.level ?? 0;
3426
+ const styleLevelProperties = styleChain.map((entry) => ({
3427
+ properties: textStyleLevelProperties(entry.style, level),
3428
+ includeRunDecorations: entry.includeRunDecorations
3429
+ }));
3430
+ const properties = computeParagraphProperties(
3431
+ context,
3432
+ paragraph.properties,
3433
+ styleLevelProperties.map((entry) => entry.properties)
3434
+ );
3435
+ return {
3436
+ ...properties !== void 0 ? { properties } : {},
3437
+ runs: paragraph.runs.map((run) => {
3438
+ const runProperties = mergeRunProperties(context, run.properties, [
3439
+ {
3440
+ properties: paragraph.properties?.defaultRunProperties,
3441
+ includeDecorations: true
3442
+ },
3443
+ ...styleLevelProperties.map((entry) => ({
3444
+ properties: entry.properties?.defaultRunProperties,
3445
+ includeDecorations: entry.includeRunDecorations
3446
+ }))
3447
+ ]);
3448
+ return {
3449
+ text: run.text,
3450
+ ...runProperties !== void 0 ? { properties: runProperties } : {}
3451
+ };
3452
+ })
3453
+ };
3454
+ }
3455
+ function buildTextStyleChain(context, textBody, inheritedBodies, placeholderType, includeInheritedStyleChain) {
3456
+ return [
3457
+ ...textBody.listStyle !== void 0 ? [{ style: textBody.listStyle, includeRunDecorations: true }] : [],
3458
+ ...includeInheritedStyleChain ? [
3459
+ ...inheritedBodies.flatMap(
3460
+ (body) => body?.listStyle !== void 0 ? [{ style: body.listStyle, includeRunDecorations: false }] : []
3461
+ ),
3462
+ ...styleEntry(getTxStyleForPlaceholder(context.master?.txStyles, placeholderType)),
3463
+ ...styleEntry(context.source.presentation.defaultTextStyle)
3464
+ ] : []
3465
+ ];
3466
+ }
3467
+ function getTxStyleForPlaceholder(txStyles, placeholderType) {
3468
+ if (txStyles === void 0) return void 0;
3469
+ if (placeholderType === void 0) return txStyles.otherStyle;
3470
+ if (placeholderType === "title" || placeholderType === "ctrTitle") return txStyles.titleStyle;
3471
+ if (placeholderType === "body" || placeholderType === "subTitle" || placeholderType === "obj") {
3472
+ return txStyles.bodyStyle;
3473
+ }
3474
+ return txStyles.otherStyle;
3475
+ }
3476
+ function textStyleLevelProperties(style, level) {
3477
+ return style.levels[level] ?? style.defaultParagraph;
3478
+ }
3479
+ function computeParagraphProperties(context, local, inherited) {
3480
+ const resolvedBulletColor = firstDefined(
3481
+ local?.bulletColor !== void 0 ? resolveColor(context, local.bulletColor) : void 0,
3482
+ ...inherited.map(
3483
+ (properties) => properties?.bulletColor !== void 0 ? resolveColor(context, properties.bulletColor) : void 0
3484
+ )
3485
+ );
3486
+ const merged = {
3487
+ ...local?.align !== void 0 ? { align: local.align } : { align: pickInheritedValue(inherited, "align") ?? "left" },
3488
+ ...local?.level !== void 0 ? { level: local.level } : { level: 0 },
3489
+ ...local?.lineSpacing !== void 0 ? { lineSpacing: local.lineSpacing } : {},
3490
+ ...local?.spaceBefore !== void 0 ? { spaceBefore: local.spaceBefore } : {},
3491
+ ...local?.spaceAfter !== void 0 ? { spaceAfter: local.spaceAfter } : {},
3492
+ ...local?.marginLeft !== void 0 ? { marginLeft: local.marginLeft } : pickInherited(inherited, "marginLeft"),
3493
+ ...local?.indent !== void 0 ? { indent: local.indent } : pickInherited(inherited, "indent"),
3494
+ ...local?.bullet !== void 0 ? { bullet: local.bullet } : pickInherited(inherited, "bullet"),
3495
+ ...local?.bulletFont !== void 0 ? { bulletFont: local.bulletFont } : pickInherited(inherited, "bulletFont"),
3496
+ ...resolvedBulletColor !== void 0 ? { bulletColor: resolvedBulletColor } : {},
3497
+ ...local?.bulletSizePct !== void 0 ? { bulletSizePct: local.bulletSizePct } : pickInherited(inherited, "bulletSizePct"),
3498
+ ...local?.tabStops !== void 0 ? { tabStops: local.tabStops } : {}
3499
+ };
3500
+ return Object.keys(merged).length > 0 ? merged : void 0;
3501
+ }
3502
+ function mergeRunProperties(context, local, inherited) {
3503
+ const merged = { ...local };
3504
+ for (const defaults of inherited) {
3505
+ if (defaults.properties === void 0) continue;
3506
+ mergeDefaultRunProperties(merged, defaults.properties, defaults.includeDecorations);
3507
+ }
3508
+ if (Object.keys(merged).length === 0) return void 0;
3509
+ const color = merged.color !== void 0 ? resolveColor(context, merged.color) : void 0;
3510
+ const withoutColor = resolveThemeRunFonts(context, omitColor(merged));
3511
+ return {
3512
+ ...withoutColor,
3513
+ ...color !== void 0 ? { color } : {}
3514
+ };
3515
+ }
3516
+ function styleEntry(style) {
3517
+ return style !== void 0 ? [{ style, includeRunDecorations: false }] : [];
3518
+ }
3519
+ function mergeDefaultRunProperties(target, defaults, includeDecorations) {
3520
+ if (includeDecorations) {
3521
+ target.bold ??= defaults.bold;
3522
+ target.italic ??= defaults.italic;
3523
+ target.underline ??= defaults.underline;
3524
+ target.strikethrough ??= defaults.strikethrough;
3525
+ target.baseline ??= defaults.baseline;
3526
+ }
3527
+ target.fontSize ??= defaults.fontSize;
3528
+ target.typeface ??= defaults.typeface;
3529
+ target.typefaceEa ??= defaults.typefaceEa;
3530
+ target.typefaceCs ??= defaults.typefaceCs;
3531
+ target.color ??= defaults.color;
3532
+ }
3533
+ function pickInherited(inherited, key) {
3534
+ const value = pickInheritedValue(inherited, key);
3535
+ const picked = {};
3536
+ if (value !== void 0) {
3537
+ picked[key] = value;
3538
+ }
3539
+ return picked;
3540
+ }
3541
+ function pickInheritedValue(inherited, key) {
3542
+ const value = inherited.find((properties) => properties?.[key] !== void 0)?.[key];
3543
+ return value;
3544
+ }
3545
+ function resolveThemeRunFonts(context, properties) {
3546
+ return {
3547
+ ...properties,
3548
+ ...properties.typeface !== void 0 ? { typeface: resolveThemeTypeface(context, properties.typeface) } : {},
3549
+ ...properties.typefaceEa !== void 0 ? { typefaceEa: resolveThemeTypeface(context, properties.typefaceEa) } : {},
3550
+ ...properties.typefaceCs !== void 0 ? { typefaceCs: resolveThemeTypeface(context, properties.typefaceCs) } : {}
3551
+ };
3552
+ }
3553
+ function resolveThemeTypeface(context, typeface) {
3554
+ const scheme = context.theme?.fontScheme;
3555
+ if (scheme === void 0) return typeface;
3556
+ switch (typeface) {
3557
+ case "+mj-lt":
3558
+ return scheme.majorLatin ?? typeface;
3559
+ case "+mn-lt":
3560
+ return scheme.minorLatin ?? typeface;
3561
+ case "+mj-ea":
3562
+ return scheme.majorEastAsian ?? scheme.majorJapanese ?? typeface;
3563
+ case "+mn-ea":
3564
+ return scheme.minorEastAsian ?? scheme.minorJapanese ?? typeface;
3565
+ case "+mj-cs":
3566
+ return scheme.majorComplexScript ?? typeface;
3567
+ case "+mn-cs":
3568
+ return scheme.minorComplexScript ?? typeface;
3569
+ default:
3570
+ return typeface;
3571
+ }
3572
+ }
3573
+ function isEmptyPlaceholder(shape) {
3574
+ if (shape.placeholder === void 0) return false;
3575
+ const paragraphs = shape.textBody?.paragraphs;
3576
+ if (paragraphs === void 0 || paragraphs.length === 0) return true;
3577
+ return !paragraphs.some((paragraph) => paragraph.runs.some((run) => run.text.length > 0));
3578
+ }
3579
+ function readRawPackageText(source, partPath) {
3580
+ const rawPart = source.packageGraph.rawParts?.find((part) => part.partPath === partPath);
3581
+ if (rawPart?.kind === "binary") return textDecoder.decode(rawPart.bytes);
3582
+ return void 0;
3583
+ }
3584
+ function numericAttr3(node, attrName) {
3585
+ if (node === void 0) return void 0;
3586
+ const value = node[`@_${attrName}`];
3587
+ if (value === void 0 || value === null) return void 0;
3588
+ const parsed = Number(value);
3589
+ return Number.isFinite(parsed) ? parsed : void 0;
3590
+ }
3591
+ function omitColor(properties) {
3592
+ const withoutColor = { ...properties };
3593
+ delete withoutColor.color;
3594
+ return withoutColor;
3595
+ }
3596
+ function firstDefined(...values) {
3597
+ return values.find((value) => value !== void 0);
3598
+ }
3599
+
3600
+ // src/reader/read-pptx.ts
3601
+ var import_fflate = require("fflate");
3602
+
3603
+ // src/reader/slide-parts.ts
3604
+ var THEME_COLOR_SLOTS = [
3605
+ "dk1",
3606
+ "lt1",
3607
+ "dk2",
3608
+ "lt2",
3609
+ "accent1",
3610
+ "accent2",
3611
+ "accent3",
3612
+ "accent4",
3613
+ "accent5",
3614
+ "accent6",
3615
+ "hlink",
3616
+ "folHlink"
3617
+ ];
3618
+ var FILL_LOCAL_NAMES = /* @__PURE__ */ new Set([
3619
+ "solidFill",
3620
+ "gradFill",
3621
+ "pattFill",
3622
+ "blipFill",
3623
+ "noFill"
3624
+ ]);
3625
+ function parseSlide(root, partPath, layoutPartPath, nextId, orderedSpTree) {
3626
+ const cSld = getChild(root, "cSld");
3627
+ const background = parseBackground(getChild(cSld, "bg"), nextId);
3628
+ const colorMapOverride = parseColorMapOverride(getChild(root, "clrMapOvr"));
3629
+ const showMasterShapes = booleanAttr(root, "showMasterSp");
3630
+ return {
3631
+ partPath,
3632
+ layoutPartPath,
3633
+ ...background !== void 0 ? { background } : {},
3634
+ ...colorMapOverride !== void 0 ? { colorMapOverride } : {},
3635
+ ...showMasterShapes !== void 0 ? { showMasterShapes } : {},
3636
+ shapes: parseShapeTree(getChild(cSld, "spTree"), partPath, nextId, orderedSpTree),
3637
+ handle: { partPath }
3638
+ };
3639
+ }
3640
+ function parseSlideLayout(root, partPath, masterPartPath, nextId, orderedSpTree) {
3641
+ const cSld = getChild(root, "cSld");
3642
+ const type = getAttr(root, "type");
3643
+ const background = parseBackground(getChild(cSld, "bg"), nextId);
3644
+ const colorMapOverride = parseColorMapOverride(getChild(root, "clrMapOvr"));
3645
+ const showMasterShapes = booleanAttr(root, "showMasterSp");
3646
+ return {
3647
+ partPath,
3648
+ masterPartPath,
3649
+ ...type !== void 0 ? { type } : {},
3650
+ ...background !== void 0 ? { background } : {},
3651
+ ...colorMapOverride !== void 0 ? { colorMapOverride } : {},
3652
+ ...showMasterShapes !== void 0 ? { showMasterShapes } : {},
3653
+ shapes: parseShapeTree(getChild(cSld, "spTree"), partPath, nextId, orderedSpTree),
3654
+ handle: { partPath }
3655
+ };
3656
+ }
3657
+ function parseSlideMaster(root, partPath, themePartPath, layoutPartPaths, nextId, orderedSpTree) {
3658
+ const cSld = getChild(root, "cSld");
3659
+ const background = parseBackground(getChild(cSld, "bg"), nextId);
3660
+ const colorMap = parseColorMap(getChild(root, "clrMap"));
3661
+ const txStyles = parseMasterTextStyles(getChild(root, "txStyles"));
3662
+ return {
3663
+ partPath,
3664
+ ...themePartPath !== void 0 ? { themePartPath } : {},
3665
+ layoutPartPaths,
3666
+ ...background !== void 0 ? { background } : {},
3667
+ ...colorMap !== void 0 ? { colorMap } : {},
3668
+ ...txStyles !== void 0 ? { txStyles } : {},
3669
+ shapes: parseShapeTree(getChild(cSld, "spTree"), partPath, nextId, orderedSpTree),
3670
+ handle: { partPath }
3671
+ };
3672
+ }
3673
+ function parseMasterTextStyles(txStyles) {
3674
+ if (txStyles === void 0) return void 0;
3675
+ const titleStyle = parseTextStyle(getChild(txStyles, "titleStyle"));
3676
+ const bodyStyle = parseTextStyle(getChild(txStyles, "bodyStyle"));
3677
+ const otherStyle = parseTextStyle(getChild(txStyles, "otherStyle"));
3678
+ const parsed = {
3679
+ ...titleStyle !== void 0 ? { titleStyle } : {},
3680
+ ...bodyStyle !== void 0 ? { bodyStyle } : {},
3681
+ ...otherStyle !== void 0 ? { otherStyle } : {}
3682
+ };
3683
+ return Object.keys(parsed).length > 0 ? parsed : void 0;
3684
+ }
3685
+ function parseTheme(root, partPath, nextId, orderedRoot) {
3686
+ const name = getAttr(root, "name");
3687
+ const themeElements = getChild(root, "themeElements");
3688
+ const colorScheme = parseColorScheme(getChild(themeElements, "clrScheme"));
3689
+ const fontScheme = parseFontScheme(getChild(themeElements, "fontScheme"));
3690
+ const formatScheme = parseFormatScheme(getChild(themeElements, "fmtScheme"), nextId, orderedRoot);
3691
+ return {
3692
+ partPath,
3693
+ ...name !== void 0 ? { name } : {},
3694
+ ...colorScheme !== void 0 ? { colorScheme } : {},
3695
+ ...fontScheme !== void 0 ? { fontScheme } : {},
3696
+ ...formatScheme !== void 0 ? { formatScheme } : {},
3697
+ handle: { partPath }
3698
+ };
3699
+ }
3700
+ function parseBackground(bg, nextId) {
3701
+ if (!bg) return void 0;
3702
+ const bgPr = getChild(bg, "bgPr");
3703
+ if (bgPr) {
3704
+ const fill = parseFill(bgPr, nextId);
3705
+ if (fill !== void 0) return { kind: "fill", fill };
3706
+ return { kind: "raw", raw: makeSidecar("p:bg", bg, nextId) };
3707
+ }
3708
+ const bgRef = getChild(bg, "bgRef");
3709
+ if (bgRef) {
3710
+ const color = parseColorElement(bgRef);
3711
+ const index = numericAttr(bgRef, "idx");
3712
+ if (color !== void 0) {
3713
+ return { kind: "styleReference", index: index ?? 0, color };
3714
+ }
3715
+ }
3716
+ return { kind: "raw", raw: makeSidecar("p:bg", bg, nextId) };
3717
+ }
3718
+ function parseColorMap(clrMap) {
3719
+ if (!clrMap) return void 0;
3720
+ const mapping = getAttrs(clrMap);
3721
+ return Object.keys(mapping).length > 0 ? { mapping } : void 0;
3722
+ }
3723
+ function parseColorMapOverride(clrMapOvr) {
3724
+ if (!clrMapOvr) return void 0;
3725
+ const override = getChild(clrMapOvr, "overrideClrMapping");
3726
+ if (!override) return void 0;
3727
+ const mapping = getAttrs(override);
3728
+ return Object.keys(mapping).length > 0 ? { mapping } : void 0;
3729
+ }
3730
+ function parseColorScheme(clrScheme) {
3731
+ if (!clrScheme) return void 0;
3732
+ const colors = {};
3733
+ for (const slot of THEME_COLOR_SLOTS) {
3734
+ const color = parseColorElement(getChild(clrScheme, slot));
3735
+ if (color !== void 0) colors[slot] = color;
3736
+ }
3737
+ return Object.keys(colors).length > 0 ? { colors } : void 0;
3738
+ }
3739
+ function parseFontScheme(fontScheme) {
3740
+ if (!fontScheme) return void 0;
3741
+ const majorFont = getChild(fontScheme, "majorFont");
3742
+ const minorFont = getChild(fontScheme, "minorFont");
3743
+ const majorLatin = getAttr(getChild(majorFont, "latin"), "typeface");
3744
+ const minorLatin = getAttr(getChild(minorFont, "latin"), "typeface");
3745
+ const majorEastAsian = resolveEastAsianFont(majorFont);
3746
+ const minorEastAsian = resolveEastAsianFont(minorFont);
3747
+ const majorComplexScript = getAttr(getChild(majorFont, "cs"), "typeface");
3748
+ const minorComplexScript = getAttr(getChild(minorFont, "cs"), "typeface");
3749
+ const majorJapanese = findScriptFont(majorFont, "Jpan");
3750
+ const minorJapanese = findScriptFont(minorFont, "Jpan");
3751
+ const scheme = {
3752
+ ...isNonEmpty(majorLatin) ? { majorLatin } : {},
3753
+ ...isNonEmpty(minorLatin) ? { minorLatin } : {},
3754
+ ...isNonEmpty(majorEastAsian) ? { majorEastAsian } : {},
3755
+ ...isNonEmpty(minorEastAsian) ? { minorEastAsian } : {},
3756
+ // Preserve explicit empty complex script fonts so scheme references can
3757
+ // resolve distinctly from missing values.
3758
+ ...majorComplexScript !== void 0 ? { majorComplexScript } : {},
3759
+ ...minorComplexScript !== void 0 ? { minorComplexScript } : {},
3760
+ ...isNonEmpty(majorJapanese) ? { majorJapanese } : {},
3761
+ ...isNonEmpty(minorJapanese) ? { minorJapanese } : {}
3762
+ };
3763
+ return Object.keys(scheme).length > 0 ? scheme : void 0;
3764
+ }
3765
+ function resolveEastAsianFont(fontNode) {
3766
+ const typeface = getAttr(getChild(fontNode, "ea"), "typeface");
3767
+ return isNonEmpty(typeface) ? typeface : findScriptFont(fontNode, "Jpan");
3768
+ }
3769
+ function findScriptFont(fontNode, script) {
3770
+ const font = getChildArray(fontNode, "font").find(
3771
+ (candidate) => getAttr(candidate, "script") === script
3772
+ );
3773
+ return getAttr(font, "typeface");
3774
+ }
3775
+ function parseFormatScheme(fmtScheme, nextId, orderedRoot) {
3776
+ if (fmtScheme === void 0) return void 0;
3777
+ const orderedFmtScheme = orderedRoot !== void 0 ? navigateOrdered(orderedRoot, ["themeElements", "fmtScheme"]) : [];
3778
+ const fillStyles = parseFillStyleList(
3779
+ getChild(fmtScheme, "fillStyleLst"),
3780
+ orderedFmtScheme,
3781
+ "fillStyleLst",
3782
+ nextId
3783
+ );
3784
+ const backgroundFillStyles = parseFillStyleList(
3785
+ getChild(fmtScheme, "bgFillStyleLst"),
3786
+ orderedFmtScheme,
3787
+ "bgFillStyleLst",
3788
+ nextId
3789
+ );
3790
+ const lineStyles = getChildArray(getChild(fmtScheme, "lnStyleLst"), "ln").flatMap((ln) => {
3791
+ const line = parseLine(ln, nextId);
3792
+ return line !== void 0 ? [line] : [];
3793
+ });
3794
+ const effectStyles = getChildArray(getChild(fmtScheme, "effectStyleLst"), "effectStyle").map(
3795
+ (effectStyle) => parseEffectList2(getChild(effectStyle, "effectLst"))
3796
+ );
3797
+ if (fillStyles.length === 0 && backgroundFillStyles.length === 0 && lineStyles.length === 0 && effectStyles.length === 0) {
3798
+ return void 0;
3799
+ }
3800
+ return { fillStyles, lineStyles, effectStyles, backgroundFillStyles };
3801
+ }
3802
+ function parseFillStyleList(list, orderedFmtScheme, listName, nextId) {
3803
+ if (list === void 0) return [];
3804
+ const orderedList = orderedFmtScheme?.find((node) => listName in node)?.[listName];
3805
+ if (!Array.isArray(orderedList)) return [];
3806
+ const orderedItems = orderedList;
3807
+ const fills = [];
3808
+ const tagCounters = {};
3809
+ for (const orderedChild of orderedItems) {
3810
+ const qualifiedName = Object.keys(orderedChild).find((key) => FILL_LOCAL_NAMES.has(key));
3811
+ if (qualifiedName === void 0) continue;
3812
+ const name = localName(qualifiedName);
3813
+ const index = tagCounters[name] ?? 0;
3814
+ tagCounters[name] = index + 1;
3815
+ const values = getChildArray(list, name);
3816
+ const value = values[index];
3817
+ if (value === void 0) continue;
3818
+ const fill = parseFill({ [qualifiedName]: value }, nextId);
3819
+ if (fill !== void 0) fills.push(fill);
3820
+ }
3821
+ return fills;
3822
+ }
3823
+ function parseEffectList2(effectList) {
3824
+ if (effectList === void 0) return void 0;
3825
+ const outerShadow = parseOuterShadow2(getChild(effectList, "outerShdw"));
3826
+ const innerShadow = parseInnerShadow2(getChild(effectList, "innerShdw"));
3827
+ const glow = parseGlow2(getChild(effectList, "glow"));
3828
+ const softEdge = parseSoftEdge2(getChild(effectList, "softEdge"));
3829
+ const parsed = {
3830
+ ...outerShadow !== void 0 ? { outerShadow } : {},
3831
+ ...innerShadow !== void 0 ? { innerShadow } : {},
3832
+ ...glow !== void 0 ? { glow } : {},
3833
+ ...softEdge !== void 0 ? { softEdge } : {}
3834
+ };
3835
+ return Object.keys(parsed).length > 0 ? parsed : void 0;
3836
+ }
3837
+ function parseOuterShadow2(node) {
3838
+ const color = parseColorElement(node);
3839
+ if (node === void 0 || color === void 0) return void 0;
3840
+ return {
3841
+ blurRadius: asEmu(numericAttr(node, "blurRad") ?? 0),
3842
+ distance: asEmu(numericAttr(node, "dist") ?? 0),
3843
+ direction: asOoxmlAngle(numericAttr(node, "dir") ?? 0),
3844
+ color,
3845
+ alignment: parseRectangleAlignment(getAttr(node, "algn"), "b"),
3846
+ rotateWithShape: getAttr(node, "rotWithShape") !== "0"
3847
+ };
3848
+ }
3849
+ function parseInnerShadow2(node) {
3850
+ const color = parseColorElement(node);
3851
+ if (node === void 0 || color === void 0) return void 0;
3852
+ return {
3853
+ blurRadius: asEmu(numericAttr(node, "blurRad") ?? 0),
3854
+ distance: asEmu(numericAttr(node, "dist") ?? 0),
3855
+ direction: asOoxmlAngle(numericAttr(node, "dir") ?? 0),
3856
+ color
3857
+ };
3858
+ }
3859
+ function parseGlow2(node) {
3860
+ const color = parseColorElement(node);
3861
+ if (node === void 0 || color === void 0) return void 0;
3862
+ return {
3863
+ radius: asEmu(numericAttr(node, "rad") ?? 0),
3864
+ color
3865
+ };
3866
+ }
3867
+ function parseSoftEdge2(node) {
3868
+ if (node === void 0) return void 0;
3869
+ return {
3870
+ radius: asEmu(numericAttr(node, "rad") ?? 0)
3871
+ };
3872
+ }
3873
+ function booleanAttr(node, name) {
3874
+ const value = getAttr(node, name);
3875
+ if (value === void 0) return void 0;
3876
+ return isTrue(value);
3877
+ }
3878
+ function isNonEmpty(value) {
3879
+ return value !== void 0 && value !== "";
3880
+ }
3881
+
3882
+ // src/reader/read-pptx.ts
3883
+ var CONTENT_TYPES_PART = "[Content_Types].xml";
3884
+ var PACKAGE_ROOT_PART = "";
3885
+ var OFFICE_DOCUMENT_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
3886
+ var SLIDE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide";
3887
+ var SLIDE_LAYOUT_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout";
3888
+ var SLIDE_MASTER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster";
3889
+ var THEME_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
3890
+ var PRESENTATION_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
3891
+ var textDecoder2 = new TextDecoder();
3892
+ function readPptx(input) {
3893
+ const entries = unzipPackage(input);
3894
+ const diagnostics = [];
3895
+ const contentTypes = readContentTypes(entries);
3896
+ const relationships = readRelationships(entries);
3897
+ const parts = [];
3898
+ const media = [];
3899
+ const rawParts = [];
3900
+ for (const [path, bytes] of entries) {
3901
+ if (path === CONTENT_TYPES_PART) continue;
3902
+ const contentType = resolveContentType(path, contentTypes.defaults, contentTypes.overrides);
3903
+ parts.push({ partPath: asPartPath(path), contentType });
3904
+ if (isMediaContentType(contentType)) {
3905
+ media.push({ partPath: asPartPath(path), contentType, bytes });
3906
+ continue;
3907
+ }
3908
+ if (isRelationshipPart(path)) continue;
3909
+ rawParts.push({ kind: "binary", partPath: asPartPath(path), contentType, bytes });
3910
+ }
3911
+ const presentation = readPresentation(
3912
+ entries,
3913
+ relationships,
3914
+ contentTypes.overrides,
3915
+ diagnostics
3916
+ );
3917
+ const hierarchy = readSlideHierarchy(entries, relationships, presentation, diagnostics);
3918
+ return {
3919
+ packageGraph: {
3920
+ contentTypes,
3921
+ parts,
3922
+ relationships,
3923
+ media,
3924
+ rawParts
3925
+ },
3926
+ presentation,
3927
+ slides: hierarchy.slides,
3928
+ slideLayouts: hierarchy.slideLayouts,
3929
+ slideMasters: hierarchy.slideMasters,
3930
+ themes: hierarchy.themes,
3931
+ diagnostics
3932
+ };
3933
+ }
3934
+ function readSlideHierarchy(entries, relationships, presentation, diagnostics) {
3935
+ const slides = [];
3936
+ const layoutPaths = new OrderedPathSet();
3937
+ for (const slidePath of presentation.slidePartPaths) {
3938
+ const part = parsePartRoot(entries, slidePath, "sld", diagnostics, true);
3939
+ if (part === void 0) continue;
3940
+ const layoutPath = resolveSingleRel(relationships, slidePath, SLIDE_LAYOUT_REL_TYPE);
3941
+ if (layoutPath === void 0) {
3942
+ diagnostics.push({
3943
+ severity: "warning",
3944
+ code: "slide-layout-unresolved",
3945
+ message: `slide '${slidePath}' has no resolvable slideLayout relationship`,
3946
+ handle: { partPath: slidePath }
3947
+ });
3948
+ } else {
3949
+ layoutPaths.add(layoutPath);
3950
+ }
3951
+ slides.push(
3952
+ parseSlide(
3953
+ part.root,
3954
+ slidePath,
3955
+ layoutPath ?? asPartPath(""),
3956
+ createSidecarIdFactory(slidePath),
3957
+ navigateOrdered(part.orderedRoot, ["cSld", "spTree"])
3958
+ )
3959
+ );
3960
+ }
3961
+ const slideLayouts = [];
3962
+ const masterPaths = new OrderedPathSet();
3963
+ for (const layoutPath of layoutPaths.values()) {
3964
+ const part = parsePartRoot(entries, layoutPath, "sldLayout", diagnostics, true);
3965
+ if (part === void 0) continue;
3966
+ const masterPath = resolveSingleRel(relationships, layoutPath, SLIDE_MASTER_REL_TYPE);
3967
+ if (masterPath !== void 0) masterPaths.add(masterPath);
3968
+ slideLayouts.push(
3969
+ parseSlideLayout(
3970
+ part.root,
3971
+ layoutPath,
3972
+ masterPath ?? asPartPath(""),
3973
+ createSidecarIdFactory(layoutPath),
3974
+ navigateOrdered(part.orderedRoot, ["cSld", "spTree"])
3975
+ )
3976
+ );
3977
+ }
3978
+ const slideMasters = [];
3979
+ const themePaths = new OrderedPathSet();
3980
+ for (const masterPath of masterPaths.values()) {
3981
+ const part = parsePartRoot(entries, masterPath, "sldMaster", diagnostics, true);
3982
+ if (part === void 0) continue;
3983
+ const themePath = resolveSingleRel(relationships, masterPath, THEME_REL_TYPE);
3984
+ if (themePath !== void 0) themePaths.add(themePath);
3985
+ const masterLayoutPaths = resolveAllRels(relationships, masterPath, SLIDE_LAYOUT_REL_TYPE);
3986
+ slideMasters.push(
3987
+ parseSlideMaster(
3988
+ part.root,
3989
+ masterPath,
3990
+ themePath,
3991
+ masterLayoutPaths,
3992
+ createSidecarIdFactory(masterPath),
3993
+ navigateOrdered(part.orderedRoot, ["cSld", "spTree"])
3994
+ )
3995
+ );
3996
+ }
3997
+ const themes = [];
3998
+ for (const themePath of themePaths.values()) {
3999
+ const part = parsePartRoot(entries, themePath, "theme", diagnostics, true);
4000
+ if (part === void 0) continue;
4001
+ themes.push(
4002
+ parseTheme(part.root, themePath, createSidecarIdFactory(themePath), part.orderedRoot)
4003
+ );
4004
+ }
4005
+ return { slides, slideLayouts, slideMasters, themes };
4006
+ }
4007
+ function parsePartRoot(entries, partPath, rootLocalName, diagnostics, includeOrderedRoot) {
4008
+ const bytes = entries.get(partPath);
4009
+ if (!bytes) {
4010
+ diagnostics.push({
4011
+ severity: "warning",
4012
+ code: "part-missing",
4013
+ message: `part '${partPath}' referenced by the package graph is missing`,
4014
+ handle: { partPath }
4015
+ });
4016
+ return void 0;
4017
+ }
4018
+ const xml = textDecoder2.decode(bytes);
4019
+ const root = getChild(parseXml(xml), rootLocalName);
4020
+ if (root === void 0) {
4021
+ diagnostics.push({
4022
+ severity: "warning",
4023
+ code: "part-root-unexpected",
4024
+ message: `part '${partPath}' does not have the expected <${rootLocalName}> root`,
4025
+ handle: { partPath }
4026
+ });
4027
+ return void 0;
4028
+ }
4029
+ const orderedRoot = includeOrderedRoot ? navigateOrdered(parseXmlOrdered(xml), [rootLocalName]) ?? [] : [];
4030
+ return { root, orderedRoot };
4031
+ }
4032
+ function resolveSingleRel(relationships, sourcePart, relType) {
4033
+ const rels = relationships.find((rel) => rel.sourcePartPath === sourcePart)?.relationships;
4034
+ const match = rels?.find((rel) => rel.type === relType && rel.targetMode !== "External");
4035
+ if (match === void 0) return void 0;
4036
+ return resolveInternalRelationshipTarget(sourcePart, match);
4037
+ }
4038
+ function resolveAllRels(relationships, sourcePart, relType) {
4039
+ const rels = relationships.find((rel) => rel.sourcePartPath === sourcePart)?.relationships ?? [];
4040
+ return rels.filter((rel) => rel.type === relType && rel.targetMode !== "External").flatMap((rel) => {
4041
+ const target = resolveInternalRelationshipTarget(sourcePart, rel);
4042
+ return target === void 0 ? [] : [target];
4043
+ });
4044
+ }
4045
+ var OrderedPathSet = class {
4046
+ seen = /* @__PURE__ */ new Set();
4047
+ order = [];
4048
+ add(path) {
4049
+ if (this.seen.has(path)) return;
4050
+ this.seen.add(path);
4051
+ this.order.push(path);
4052
+ }
4053
+ values() {
4054
+ return this.order;
4055
+ }
4056
+ };
4057
+ function unzipPackage(input) {
4058
+ const unzipped = (0, import_fflate.unzipSync)(input);
4059
+ const entries = /* @__PURE__ */ new Map();
4060
+ for (const [path, bytes] of Object.entries(unzipped)) {
4061
+ if (path.endsWith("/")) continue;
4062
+ entries.set(path, bytes);
4063
+ }
4064
+ return entries;
4065
+ }
4066
+ function readContentTypes(entries) {
4067
+ const bytes = entries.get(CONTENT_TYPES_PART);
4068
+ if (!bytes) return { defaults: [], overrides: [] };
4069
+ const root = getChild(parseXml(textDecoder2.decode(bytes)), "Types");
4070
+ const defaults = [];
4071
+ for (const node of getChildArray(root, "Default")) {
4072
+ const extension = getAttr(node, "Extension");
4073
+ const contentType = getAttr(node, "ContentType");
4074
+ if (extension === void 0 || contentType === void 0) continue;
4075
+ defaults.push({ extension, contentType });
4076
+ }
4077
+ const overrides = [];
4078
+ for (const node of getChildArray(root, "Override")) {
4079
+ const partName = getAttr(node, "PartName");
4080
+ const contentType = getAttr(node, "ContentType");
4081
+ if (partName === void 0 || contentType === void 0) continue;
4082
+ overrides.push({ partName: asPartPath(stripLeadingSlash(partName)), contentType });
4083
+ }
4084
+ return { defaults, overrides };
4085
+ }
4086
+ function readRelationships(entries) {
4087
+ const result = [];
4088
+ for (const [path, bytes] of entries) {
4089
+ if (!isRelationshipPart(path)) continue;
4090
+ const root = getChild(parseXml(textDecoder2.decode(bytes)), "Relationships");
4091
+ const relationships = [];
4092
+ for (const node of getChildArray(root, "Relationship")) {
4093
+ const id = getAttr(node, "Id");
4094
+ const type = getAttr(node, "Type");
4095
+ const target = getAttr(node, "Target");
4096
+ if (id === void 0 || type === void 0 || target === void 0) continue;
4097
+ const targetMode = parseRelationshipTargetMode(getAttr(node, "TargetMode"));
4098
+ relationships.push({
4099
+ id: asRelationshipId(id),
4100
+ type,
4101
+ target,
4102
+ ...targetMode !== void 0 ? { targetMode } : {}
4103
+ });
4104
+ }
4105
+ result.push({ sourcePartPath: relationshipsSourcePartPath(path), relationships });
4106
+ }
4107
+ return result;
4108
+ }
4109
+ function readPresentation(entries, relationships, overrides, diagnostics) {
4110
+ const presentationPath = locatePresentationPart(relationships, overrides);
4111
+ if (presentationPath === void 0) {
4112
+ throw new Error("readPptx: presentation part not found; input is not a valid PPTX package");
4113
+ }
4114
+ const bytes = entries.get(presentationPath);
4115
+ if (!bytes) {
4116
+ throw new Error(
4117
+ `readPptx: presentation part '${presentationPath}' is missing from the package`
4118
+ );
4119
+ }
4120
+ const presentationPartPath = asPartPath(presentationPath);
4121
+ const root = getChild(parseXml(textDecoder2.decode(bytes)), "presentation");
4122
+ if (root === void 0) {
4123
+ throw new Error(
4124
+ `readPptx: part '${presentationPath}' is not a presentation part (missing p:presentation root)`
4125
+ );
4126
+ }
4127
+ const slideSize = readSlideSize(root);
4128
+ const defaultTextStyle = parseTextStyle(getChild(root, "defaultTextStyle"));
4129
+ const presentationRels = relationships.find(
4130
+ (rel) => rel.sourcePartPath === presentationPath
4131
+ )?.relationships;
4132
+ const slidePartPaths = [];
4133
+ const sldIdLst = getChild(root, "sldIdLst");
4134
+ for (const sldId of getChildArray(sldIdLst, "sldId")) {
4135
+ const relId = getNamespacedAttr(sldId, "id");
4136
+ if (relId === void 0) continue;
4137
+ const handle = { partPath: presentationPartPath, relationshipId: asRelationshipId(relId) };
4138
+ const relationship = presentationRels?.find((rel) => rel.id === relId);
4139
+ if (relationship === void 0) {
4140
+ diagnostics.push({
4141
+ severity: "warning",
4142
+ code: "slide-relationship-unresolved",
4143
+ message: `slide relationship '${relId}' referenced by presentation could not be resolved`,
4144
+ handle
4145
+ });
4146
+ continue;
4147
+ }
4148
+ if (relationship.type !== SLIDE_REL_TYPE || relationship.targetMode === "External") {
4149
+ diagnostics.push({
4150
+ severity: "warning",
4151
+ code: "slide-relationship-invalid",
4152
+ message: `relationship '${relId}' referenced by p:sldId is not an internal slide relationship`,
4153
+ handle
4154
+ });
4155
+ continue;
4156
+ }
4157
+ slidePartPaths.push(
4158
+ asPartPath(resolveRelationshipTarget(presentationPath, relationship.target))
4159
+ );
4160
+ }
4161
+ return {
4162
+ partPath: presentationPartPath,
4163
+ ...slideSize !== void 0 ? { slideSize } : {},
4164
+ ...defaultTextStyle !== void 0 ? { defaultTextStyle } : {},
4165
+ slidePartPaths,
4166
+ handle: { partPath: presentationPartPath }
4167
+ };
4168
+ }
4169
+ function readSlideSize(presentationRoot) {
4170
+ const sldSz = getChild(presentationRoot, "sldSz");
4171
+ const cx = getAttr(sldSz, "cx");
4172
+ const cy = getAttr(sldSz, "cy");
4173
+ if (cx === void 0 || cy === void 0) return void 0;
4174
+ const width = Number(cx);
4175
+ const height = Number(cy);
4176
+ if (!Number.isFinite(width) || !Number.isFinite(height)) return void 0;
4177
+ return { width: asEmu(width), height: asEmu(height) };
4178
+ }
4179
+ function locatePresentationPart(relationships, overrides) {
4180
+ const rootRels = relationships.find(
4181
+ (rel) => rel.sourcePartPath === PACKAGE_ROOT_PART
4182
+ )?.relationships;
4183
+ const officeDocumentRel = rootRels?.find(
4184
+ (rel) => rel.type === OFFICE_DOCUMENT_REL_TYPE && rel.targetMode !== "External"
4185
+ );
4186
+ if (officeDocumentRel !== void 0) {
4187
+ return resolveRelationshipTarget(PACKAGE_ROOT_PART, officeDocumentRel.target);
4188
+ }
4189
+ const override = overrides.find((entry) => entry.contentType === PRESENTATION_CONTENT_TYPE);
4190
+ return override?.partName;
4191
+ }
4192
+ var MEDIA_CONTENT_TYPE_PREFIXES = ["image/", "audio/", "video/"];
4193
+ function isMediaContentType(contentType) {
4194
+ return MEDIA_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.startsWith(prefix));
4195
+ }
4196
+ function resolveContentType(path, defaults, overrides) {
4197
+ const override = overrides.find((entry) => entry.partName === path);
4198
+ if (override !== void 0) return override.contentType;
4199
+ const extension = extensionOf(path);
4200
+ if (extension !== void 0) {
4201
+ const fallback = defaults.find(
4202
+ (entry) => entry.extension.toLowerCase() === extension.toLowerCase()
4203
+ );
4204
+ if (fallback !== void 0) return fallback.contentType;
4205
+ }
4206
+ return "application/octet-stream";
4207
+ }
4208
+ function extensionOf(path) {
4209
+ const dot = path.lastIndexOf(".");
4210
+ const slash = path.lastIndexOf("/");
4211
+ if (dot === -1 || dot < slash) return void 0;
4212
+ return path.slice(dot + 1);
4213
+ }
4214
+ function stripLeadingSlash(path) {
4215
+ return path.startsWith("/") ? path.slice(1) : path;
4216
+ }
4217
+
4218
+ // src/writer/write-pptx.ts
4219
+ var import_fast_xml_parser2 = require("fast-xml-parser");
4220
+ var import_fflate2 = require("fflate");
4221
+ var CONTENT_TYPES_PART2 = "[Content_Types].xml";
4222
+ var RELS_CONTENT_TYPE = "application/vnd.openxmlformats-package.relationships+xml";
4223
+ var XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
4224
+ var textEncoder = new TextEncoder();
4225
+ var textDecoder3 = new TextDecoder();
4226
+ var xmlBuilder = new import_fast_xml_parser2.XMLBuilder({
4227
+ ignoreAttributes: false,
4228
+ attributeNamePrefix: "@_",
4229
+ format: false,
4230
+ suppressEmptyNode: true
4231
+ });
4232
+ function writePptx(source) {
4233
+ const textRunEdits = source.edits?.filter(isTextRunEdit) ?? [];
4234
+ const paragraphTextEdits = source.edits?.filter(isParagraphTextEdit) ?? [];
4235
+ const shapeTransformEdits = source.edits?.filter(isShapeTransformEdit) ?? [];
4236
+ validateEdits(textRunEdits, paragraphTextEdits, shapeTransformEdits);
4237
+ const dirtyPartPaths = new Set(
4238
+ [...textRunEdits, ...paragraphTextEdits, ...shapeTransformEdits].map(
4239
+ (edit) => edit.handle.partPath
4240
+ )
4241
+ );
4242
+ const files = {
4243
+ [CONTENT_TYPES_PART2]: encodeXml(serializeContentTypes(source.packageGraph.contentTypes))
4244
+ };
4245
+ const written = /* @__PURE__ */ new Set([CONTENT_TYPES_PART2]);
4246
+ for (const relationships of source.packageGraph.relationships) {
4247
+ const relsPath = relationshipsPartPath(relationships.sourcePartPath);
4248
+ files[relsPath] = encodeXml(serializeRelationships(relationships));
4249
+ written.add(relsPath);
4250
+ }
4251
+ for (const media of source.packageGraph.media) {
4252
+ files[media.partPath] = media.bytes;
4253
+ written.add(media.partPath);
4254
+ }
4255
+ for (const rawPart of source.packageGraph.rawParts ?? []) {
4256
+ if (dirtyPartPaths.has(rawPart.partPath)) continue;
4257
+ files[rawPart.partPath] = serializeRawPackagePart(rawPart);
4258
+ written.add(rawPart.partPath);
4259
+ }
4260
+ for (const partPath of dirtyPartPaths) {
4261
+ files[partPath] = serializeDirtyXmlPart(
4262
+ source,
4263
+ partPath,
4264
+ textRunEdits,
4265
+ paragraphTextEdits,
4266
+ shapeTransformEdits
4267
+ );
4268
+ written.add(partPath);
4269
+ }
4270
+ for (const part of source.packageGraph.parts) {
4271
+ if (written.has(part.partPath)) continue;
4272
+ if (part.contentType === RELS_CONTENT_TYPE || isRelationshipPart(part.partPath)) continue;
4273
+ throw new Error(
4274
+ `writePptx: no preserved package material for part '${part.partPath}'; edited part generation is not implemented in the no-edit writer`
4275
+ );
4276
+ }
4277
+ return (0, import_fflate2.zipSync)(files);
4278
+ }
4279
+ function isTextRunEdit(edit) {
4280
+ return edit.kind === "replaceTextRunPlainText";
4281
+ }
4282
+ function isParagraphTextEdit(edit) {
4283
+ return edit.kind === "replaceParagraphPlainText";
4284
+ }
4285
+ function isShapeTransformEdit(edit) {
4286
+ return edit.kind === "updateShapeTransform";
4287
+ }
4288
+ function serializeDirtyXmlPart(source, partPath, textRunEdits, paragraphTextEdits, shapeTransformEdits) {
4289
+ const rawPart = source.packageGraph.rawParts?.find((part) => part.partPath === partPath);
4290
+ if (rawPart === void 0) {
4291
+ throw new Error(`writePptx: dirty part '${partPath}' has no preserved raw package material`);
4292
+ }
4293
+ if (rawPart.kind !== "binary") {
4294
+ throw new Error(`writePptx: dirty XML tree part '${partPath}' patching is not implemented`);
4295
+ }
4296
+ const root = parseXml(textDecoder3.decode(rawPart.bytes));
4297
+ for (const edit of paragraphTextEdits.filter((edit2) => edit2.handle.partPath === partPath)) {
4298
+ applyParagraphTextEdit(root, edit);
4299
+ }
4300
+ for (const edit of textRunEdits.filter((edit2) => edit2.handle.partPath === partPath)) {
4301
+ applyTextRunEdit(root, edit);
4302
+ }
4303
+ for (const edit of shapeTransformEdits.filter((edit2) => edit2.handle.partPath === partPath)) {
4304
+ applyShapeTransformEdit(root, edit);
4305
+ }
4306
+ return encodeXml(XML_DECLARATION + xmlBuilder.build(stripXmlProcessingInstruction(root)));
4307
+ }
4308
+ function stripXmlProcessingInstruction(root) {
4309
+ const stripped = { ...root };
4310
+ delete stripped["?xml"];
4311
+ return stripped;
4312
+ }
4313
+ function applyTextRunEdit(root, edit) {
4314
+ const locator = parseTextRunLocator(edit.handle.nodeId);
4315
+ const slide = getChild(root, "sld");
4316
+ const cSld = getChild(slide, "cSld");
4317
+ const spTree = getChild(cSld, "spTree");
4318
+ const shape = locateShape(spTree, locator);
4319
+ const paragraphs = getChildArray(getChild(shape, "txBody"), "p");
4320
+ const paragraph = paragraphs[locator.paragraphIndex];
4321
+ const run = getChildArray(paragraph, "r")[locator.runIndex];
4322
+ if (run === void 0) {
4323
+ throw new Error(
4324
+ `writePptx: text run handle '${edit.handle.nodeId}' no longer matches source XML`
4325
+ );
4326
+ }
4327
+ setChildText(run, "t", edit.text);
4328
+ }
4329
+ function applyParagraphTextEdit(root, edit) {
4330
+ const locator = parseParagraphLocator(edit.handle.nodeId);
4331
+ const slide = getChild(root, "sld");
4332
+ const cSld = getChild(slide, "cSld");
4333
+ const spTree = getChild(cSld, "spTree");
4334
+ const shape = locateShape(spTree, locator);
4335
+ const paragraphs = getChildArray(getChild(shape, "txBody"), "p");
4336
+ const paragraph = locatePhysicalParagraphForTextEdit(paragraphs, locator, edit.handle.nodeId);
4337
+ if (paragraph === void 0) {
4338
+ throw new Error(
4339
+ `writePptx: paragraph handle '${edit.handle.nodeId}' no longer matches source XML`
4340
+ );
4341
+ }
4342
+ replaceParagraphRunsWithSingleTextRun(paragraph, edit.text);
4343
+ }
4344
+ function applyShapeTransformEdit(root, edit) {
4345
+ const locator = parseShapeLocator(edit.handle);
4346
+ const slide = getChild(root, "sld");
4347
+ const cSld = getChild(slide, "cSld");
4348
+ const spTree = getChild(cSld, "spTree");
4349
+ const shape = locateShapeTreeNode(spTree, locator);
4350
+ const xfrm = getShapeTransformNode(shape);
4351
+ if (xfrm === void 0) {
4352
+ throw new Error(
4353
+ `writePptx: shape transform handle '${String(
4354
+ edit.handle.nodeId ?? edit.handle.orderingSlot ?? ""
4355
+ )}' no longer matches source XML with xfrm`
4356
+ );
4357
+ }
4358
+ const off = getChild(xfrm, "off");
4359
+ const ext = getChild(xfrm, "ext");
4360
+ if (off === void 0 || ext === void 0) {
4361
+ throw new Error("writePptx: shape transform xfrm must contain off and ext");
4362
+ }
4363
+ off["@_x"] = String(edit.offsetX);
4364
+ off["@_y"] = String(edit.offsetY);
4365
+ ext["@_cx"] = String(edit.width);
4366
+ ext["@_cy"] = String(edit.height);
4367
+ }
4368
+ function parseShapeLocator(handle) {
4369
+ if (handle.nodeId !== void 0) return { nodeId: String(handle.nodeId) };
4370
+ throw new Error("writePptx: shape transform edit requires nodeId in handle");
4371
+ }
4372
+ function parseTextRunLocator(nodeId) {
4373
+ const value = String(nodeId ?? "");
4374
+ const byShapeId = /^text:shape:(.+):p:(\d+):r:(\d+)$/.exec(value);
4375
+ if (byShapeId !== null) {
4376
+ return {
4377
+ shapeNodeId: byShapeId[1],
4378
+ paragraphIndex: Number(byShapeId[2]),
4379
+ runIndex: Number(byShapeId[3])
4380
+ };
4381
+ }
4382
+ const byShapeSlot = /^text:shapeSlot:(\d+):p:(\d+):r:(\d+)$/.exec(value);
4383
+ if (byShapeSlot !== null) {
4384
+ return {
4385
+ shapeOrderingSlot: Number(byShapeSlot[1]),
4386
+ paragraphIndex: Number(byShapeSlot[2]),
4387
+ runIndex: Number(byShapeSlot[3])
4388
+ };
4389
+ }
4390
+ throw new Error(`writePptx: unsupported text run handle '${value}'`);
4391
+ }
4392
+ function parseParagraphLocator(nodeId) {
4393
+ const value = String(nodeId ?? "");
4394
+ const byShapeId = /^text:shape:(.+):p:(\d+)$/.exec(value);
4395
+ if (byShapeId !== null) {
4396
+ return {
4397
+ shapeNodeId: byShapeId[1],
4398
+ paragraphIndex: Number(byShapeId[2])
4399
+ };
4400
+ }
4401
+ const byShapeSlot = /^text:shapeSlot:(\d+):p:(\d+)$/.exec(value);
4402
+ if (byShapeSlot !== null) {
4403
+ return {
4404
+ shapeOrderingSlot: Number(byShapeSlot[1]),
4405
+ paragraphIndex: Number(byShapeSlot[2])
4406
+ };
4407
+ }
4408
+ throw new Error(`writePptx: unsupported paragraph handle '${value}'`);
4409
+ }
4410
+ function locateShape(spTree, locator) {
4411
+ const shapes = getChildArray(spTree, "sp");
4412
+ if (locator.shapeNodeId !== void 0) {
4413
+ return shapes.find(
4414
+ (shape) => getAttr(getChild(getChild(shape, "nvSpPr"), "cNvPr"), "id") === locator.shapeNodeId
4415
+ );
4416
+ }
4417
+ if (locator.shapeOrderingSlot === void 0) return void 0;
4418
+ return getShapeByOrderingSlot(spTree, locator.shapeOrderingSlot);
4419
+ }
4420
+ function locateShapeTreeNode(spTree, locator) {
4421
+ const shapeKeys = /* @__PURE__ */ new Set(["sp", "pic", "cxnSp", "graphicFrame", "grpSp"]);
4422
+ if (!spTree) return void 0;
4423
+ for (const key of Object.keys(spTree)) {
4424
+ if (key.startsWith("@_") || !shapeKeys.has(localName(key))) continue;
4425
+ const value = spTree[key];
4426
+ const items = Array.isArray(value) ? unsafeOoxmlBoundaryAssertion(value) : [value];
4427
+ const found = items.find(
4428
+ (item) => getShapeTreeNodeId(unsafeOoxmlBoundaryAssertion(item)) === locator.nodeId
4429
+ );
4430
+ if (found !== void 0) return unsafeOoxmlBoundaryAssertion(found);
4431
+ }
4432
+ return void 0;
4433
+ }
4434
+ function getShapeByOrderingSlot(spTree, orderingSlot) {
4435
+ if (!spTree) return void 0;
4436
+ let currentSlot = 0;
4437
+ for (const key of Object.keys(spTree)) {
4438
+ if (key.startsWith("@_")) continue;
4439
+ const local = localName(key);
4440
+ if (local === "nvGrpSpPr" || local === "grpSpPr") continue;
4441
+ const value = spTree[key];
4442
+ const items = Array.isArray(value) ? value : [value];
4443
+ for (const item of items) {
4444
+ if (currentSlot === orderingSlot) {
4445
+ return local === "sp" ? unsafeOoxmlBoundaryAssertion(item) : void 0;
4446
+ }
4447
+ currentSlot++;
4448
+ }
4449
+ }
4450
+ return void 0;
4451
+ }
4452
+ function getShapeTreeNodeId(node) {
4453
+ const nonVisualProperties = getChild(node, "nvSpPr") ?? getChild(node, "nvPicPr") ?? getChild(node, "nvCxnSpPr") ?? getChild(node, "nvGrpSpPr") ?? getChild(node, "nvGraphicFramePr");
4454
+ return getAttr(getChild(nonVisualProperties, "cNvPr"), "id");
4455
+ }
4456
+ function getShapeTransformNode(shape) {
4457
+ if (shape === void 0) return void 0;
4458
+ return getChild(getChild(shape, "spPr"), "xfrm") ?? getChild(getChild(shape, "grpSpPr"), "xfrm") ?? getChild(shape, "xfrm");
4459
+ }
4460
+ function setChildText(node, name, text) {
4461
+ for (const key of Object.keys(node)) {
4462
+ if (key.startsWith("@_")) continue;
4463
+ if (localName(key) !== name) continue;
4464
+ const value = node[key];
4465
+ if (Array.isArray(value)) {
4466
+ value[0] = textElementValue(value[0], text);
4467
+ return;
4468
+ }
4469
+ node[key] = textElementValue(value, text);
4470
+ return;
4471
+ }
4472
+ node[`a:${name}`] = textRequiresPreserve(text) ? { "@_xml:space": "preserve", "#text": text } : text;
4473
+ }
4474
+ function replaceParagraphRunsWithSingleTextRun(paragraph, text) {
4475
+ const firstRunProperties = getChild(getFirstRunLikeNode(paragraph), "rPr");
4476
+ const replacementRun = {
4477
+ ...firstRunProperties !== void 0 ? { "a:rPr": cloneXmlNode(firstRunProperties) } : {},
4478
+ "a:t": textRequiresPreserve(text) ? { "@_xml:space": "preserve", "#text": text } : text
4479
+ };
4480
+ const attrs = [];
4481
+ const paragraphProperties = [];
4482
+ const middleChildren = [];
4483
+ const endProperties = [];
4484
+ for (const [key, value] of Object.entries(paragraph)) {
4485
+ if (key.startsWith("@_")) {
4486
+ attrs.push([key, value]);
4487
+ continue;
4488
+ }
4489
+ const local = localName(key);
4490
+ if (isRunLikeLocalName(local)) continue;
4491
+ if (local === "pPr") paragraphProperties.push([key, value]);
4492
+ else if (local === "endParaRPr") endProperties.push([key, value]);
4493
+ else middleChildren.push([key, value]);
4494
+ }
4495
+ replaceNodeEntries(paragraph, [
4496
+ ...attrs,
4497
+ ...paragraphProperties,
4498
+ ["a:r", replacementRun],
4499
+ ...middleChildren,
4500
+ ...endProperties
4501
+ ]);
4502
+ }
4503
+ function getFirstRunLikeNode(paragraph) {
4504
+ for (const key of Object.keys(paragraph)) {
4505
+ if (key.startsWith("@_")) continue;
4506
+ if (!isRunLikeLocalName(localName(key))) continue;
4507
+ const value = paragraph[key];
4508
+ return Array.isArray(value) ? unsafeOoxmlBoundaryAssertion(value[0]) : unsafeOoxmlBoundaryAssertion(value);
4509
+ }
4510
+ return void 0;
4511
+ }
4512
+ function isRunLikeLocalName(name) {
4513
+ return name === "r" || name === "fld" || name === "br";
4514
+ }
4515
+ function locatePhysicalParagraphForTextEdit(paragraphs, locator, handleNodeId) {
4516
+ let logicalParagraphIndex = 0;
4517
+ for (const paragraph of paragraphs) {
4518
+ const logicalCount = getLogicalParagraphCount(paragraph);
4519
+ if (locator.paragraphIndex >= logicalParagraphIndex && locator.paragraphIndex < logicalParagraphIndex + logicalCount) {
4520
+ if (logicalCount > 1) {
4521
+ throw new Error(
4522
+ `writePptx: paragraph handle '${handleNodeId}' references an interleaved bullet paragraph split by the reader; paragraph replacement is not supported for this source XML`
4523
+ );
4524
+ }
4525
+ return paragraph;
4526
+ }
4527
+ logicalParagraphIndex += logicalCount;
4528
+ }
4529
+ return void 0;
4530
+ }
4531
+ function getLogicalParagraphCount(paragraph) {
4532
+ const bulletParagraphProperties = getChildArray(paragraph, "pPr").filter(
4533
+ (properties) => getChild(properties, "buChar") !== void 0 || getChild(properties, "buAutoNum") !== void 0
4534
+ );
4535
+ return Math.max(1, bulletParagraphProperties.length);
4536
+ }
4537
+ function replaceNodeEntries(node, entries) {
4538
+ for (const key of Object.keys(node)) delete node[key];
4539
+ for (const [key, value] of entries) node[key] = value;
4540
+ }
4541
+ function cloneXmlNode(node) {
4542
+ return Object.fromEntries(
4543
+ Object.entries(node).map(([key, value]) => [key, cloneXmlValue(value)])
4544
+ );
4545
+ }
4546
+ function cloneXmlValue(value) {
4547
+ if (Array.isArray(value)) return value.map(cloneXmlValue);
4548
+ if (typeof value === "object" && value !== null) {
4549
+ return cloneXmlNode(unsafeOoxmlBoundaryAssertion(value));
4550
+ }
4551
+ return value;
4552
+ }
4553
+ function textElementValue(existing, text) {
4554
+ if (typeof existing === "object" && existing !== null && !Array.isArray(existing)) {
4555
+ const next = { ...unsafeOoxmlBoundaryAssertion(existing), "#text": text };
4556
+ if (textRequiresPreserve(text)) next["@_xml:space"] = "preserve";
4557
+ else delete next["@_xml:space"];
4558
+ return next;
4559
+ }
4560
+ return textRequiresPreserve(text) ? { "@_xml:space": "preserve", "#text": text } : text;
4561
+ }
4562
+ function textRequiresPreserve(text) {
4563
+ return text.startsWith(" ") || text.endsWith(" ");
4564
+ }
4565
+ function validateEdits(textRunEdits, paragraphTextEdits, shapeTransformEdits) {
4566
+ const runKeys = /* @__PURE__ */ new Set();
4567
+ for (const edit of textRunEdits) {
4568
+ const key = editHandleNodeKey(edit);
4569
+ if (runKeys.has(key)) {
4570
+ throw new Error(`writePptx: conflicting text run edits for handle '${edit.handle.nodeId}'`);
4571
+ }
4572
+ runKeys.add(key);
4573
+ }
4574
+ const paragraphKeys = /* @__PURE__ */ new Set();
4575
+ for (const edit of paragraphTextEdits) {
4576
+ const key = editHandleNodeKey(edit);
4577
+ if (paragraphKeys.has(key)) {
4578
+ throw new Error(
4579
+ `writePptx: conflicting paragraph text edits for handle '${edit.handle.nodeId}'`
4580
+ );
4581
+ }
4582
+ paragraphKeys.add(key);
4583
+ }
4584
+ for (const runEdit of textRunEdits) {
4585
+ const paragraphKey = textRunParagraphEditKey(runEdit);
4586
+ if (paragraphKey !== void 0 && paragraphKeys.has(paragraphKey)) {
4587
+ throw new Error(
4588
+ `writePptx: conflicting text run and paragraph edits for handle '${runEdit.handle.nodeId}'`
4589
+ );
4590
+ }
4591
+ }
4592
+ const shapeKeys = /* @__PURE__ */ new Set();
4593
+ for (const edit of shapeTransformEdits) {
4594
+ const key = editHandleNodeKey(edit);
4595
+ if (shapeKeys.has(key)) {
4596
+ throw new Error(
4597
+ `writePptx: conflicting shape transform edits for handle '${String(edit.handle.nodeId)}'`
4598
+ );
4599
+ }
4600
+ shapeKeys.add(key);
4601
+ }
4602
+ }
4603
+ function editHandleNodeKey(edit) {
4604
+ return [edit.handle.partPath, edit.handle.nodeId ?? "", edit.handle.relationshipId ?? ""].join(
4605
+ "\0"
4606
+ );
4607
+ }
4608
+ function textRunParagraphEditKey(edit) {
4609
+ const nodeId = String(edit.handle.nodeId ?? "");
4610
+ const byShapeId = /^(text:shape:.+:p:\d+):r:\d+$/.exec(nodeId);
4611
+ const byShapeSlot = /^(text:shapeSlot:\d+:p:\d+):r:\d+$/.exec(nodeId);
4612
+ const paragraphNodeId = byShapeId?.[1] ?? byShapeSlot?.[1];
4613
+ if (paragraphNodeId === void 0) return void 0;
4614
+ return [edit.handle.partPath, paragraphNodeId, edit.handle.relationshipId ?? ""].join("\0");
4615
+ }
4616
+ function serializeContentTypes(contentTypes) {
4617
+ const defaults = contentTypes.defaults.map(
4618
+ (entry) => `<Default Extension="${escapeAttribute(entry.extension)}" ContentType="${escapeAttribute(entry.contentType)}"/>`
4619
+ ).join("");
4620
+ const overrides = contentTypes.overrides.map(
4621
+ (entry) => `<Override PartName="/${escapeAttribute(entry.partName)}" ContentType="${escapeAttribute(entry.contentType)}"/>`
4622
+ ).join("");
4623
+ return XML_DECLARATION + `<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">` + defaults + overrides + `</Types>`;
4624
+ }
4625
+ function serializeRelationships(partRelationships) {
4626
+ const relationships = partRelationships.relationships.map((relationship) => {
4627
+ const targetMode = relationship.targetMode === void 0 ? "" : ` TargetMode="${escapeAttribute(relationship.targetMode)}"`;
4628
+ return `<Relationship Id="${escapeAttribute(relationship.id)}" Type="${escapeAttribute(relationship.type)}" Target="${escapeAttribute(relationship.target)}"${targetMode}/>`;
4629
+ }).join("");
4630
+ return XML_DECLARATION + `<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">` + relationships + `</Relationships>`;
4631
+ }
4632
+ function serializeRawPackagePart(rawPart) {
4633
+ if (rawPart.kind === "binary") return rawPart.bytes;
4634
+ return encodeXml(XML_DECLARATION + serializeRawNode(rawPart.xml));
4635
+ }
4636
+ function serializeRawNode(node) {
4637
+ const attributes = node.attributes === void 0 ? "" : Object.entries(node.attributes).map(([name, value]) => ` ${name}="${escapeAttribute(value)}"`).join("");
4638
+ const text = node.text === void 0 ? "" : escapeText(node.text);
4639
+ const children = node.children?.map((child) => serializeRawNode(child)).join("") ?? "";
4640
+ if (text !== "" && children !== "") {
4641
+ throw new Error(
4642
+ `writePptx: raw XML part '${node.name}' contains mixed text/element content; ordered mixed-content serialization is not implemented in the no-edit writer`
4643
+ );
4644
+ }
4645
+ if (text === "" && children === "") return `<${node.name}${attributes}/>`;
4646
+ return `<${node.name}${attributes}>${text}${children}</${node.name}>`;
4647
+ }
4648
+ function encodeXml(xml) {
4649
+ return textEncoder.encode(xml);
4650
+ }
4651
+ function escapeAttribute(value) {
4652
+ return value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
4653
+ }
4654
+ function escapeText(value) {
4655
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
4656
+ }
4657
+ // Annotate the CommonJS export names for ESM import in node:
4658
+ 0 && (module.exports = {
4659
+ asEmu,
4660
+ asHundredthPt,
4661
+ asOoxmlAngle,
4662
+ asOoxmlPercent,
4663
+ asPartPath,
4664
+ asPt,
4665
+ asRawSidecarId,
4666
+ asRelationshipId,
4667
+ asSourceNodeId,
4668
+ createComputedView,
4669
+ findParagraphBySourceHandle,
4670
+ findShapeNodeBySourceHandle,
4671
+ findTextRunBySourceHandle,
4672
+ readPptx,
4673
+ replaceParagraphPlainText,
4674
+ replaceTextRunPlainText,
4675
+ updateShapeTransform,
4676
+ writePptx
4677
+ });