deckjsx 0.8.1 → 0.8.3

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.
@@ -63,8 +63,15 @@ const EMU_PER_INCH = 914400;
63
63
  const POINTS_PER_INCH = 72;
64
64
  const DEFAULT_FONT_SIZE_PT = 16 / 96 * 72;
65
65
  const CH_WIDTH_RATIO = .5;
66
- const DECK_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:in|pt|px|%|em|rem|vh|vw|ch)$/i;
67
- const DECK_POINT_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:pt|in|px|em|rem|vh|vw|ch)$/i;
66
+ const DECK_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:in|cm|mm|q|pt|pc|px|%|em|rem|vh|vw|vmin|vmax|ch)$/i;
67
+ const DECK_POINT_LENGTH_PATTERN = /^[-+]?(?:\d+|\d*\.\d+)(?:in|cm|mm|q|pt|pc|px|em|rem|vh|vw|vmin|vmax|ch)$/i;
68
+ const CSS_WIDE_KEYWORDS = new Set([
69
+ "initial",
70
+ "inherit",
71
+ "unset",
72
+ "revert",
73
+ "revert-layer"
74
+ ]);
68
75
  function pointsToEmu(value) {
69
76
  return value / 72 * EMU_PER_INCH;
70
77
  }
@@ -76,86 +83,103 @@ function parsePercentage(value) {
76
83
  function resolvePointUnitBase(context) {
77
84
  return context?.fontSizePt ?? DEFAULT_FONT_SIZE_PT;
78
85
  }
86
+ function absoluteLengthInInches(normalized) {
87
+ if (normalized.endsWith("vmin") || normalized.endsWith("vmax")) return;
88
+ if (normalized.endsWith("in")) return Number.parseFloat(normalized.slice(0, -2));
89
+ if (normalized.endsWith("cm")) return Number.parseFloat(normalized.slice(0, -2)) / 2.54;
90
+ if (normalized.endsWith("mm")) return Number.parseFloat(normalized.slice(0, -2)) / 25.4;
91
+ if (normalized.endsWith("q")) return Number.parseFloat(normalized.slice(0, -1)) / 101.6;
92
+ if (normalized.endsWith("pt")) return Number.parseFloat(normalized.slice(0, -2)) / 72;
93
+ if (normalized.endsWith("pc")) return Number.parseFloat(normalized.slice(0, -2)) / 6;
94
+ if (normalized.endsWith("px")) return Number.parseFloat(normalized.slice(0, -2)) / 96;
95
+ }
96
+ function resolveViewportEmu(normalized, context, errorContext) {
97
+ if (normalized.endsWith("vw")) {
98
+ const viewportWidthEmu = context?.viewportWidthEmu;
99
+ if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport ${errorContext} without viewport context: ${normalized}`);
100
+ return viewportWidthEmu * Number.parseFloat(normalized.slice(0, -2)) / 100;
101
+ }
102
+ if (normalized.endsWith("vh")) {
103
+ const viewportHeightEmu = context?.viewportHeightEmu;
104
+ if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport ${errorContext} without viewport context: ${normalized}`);
105
+ return viewportHeightEmu * Number.parseFloat(normalized.slice(0, -2)) / 100;
106
+ }
107
+ if (normalized.endsWith("vmin") || normalized.endsWith("vmax")) {
108
+ const viewportWidthEmu = context?.viewportWidthEmu;
109
+ const viewportHeightEmu = context?.viewportHeightEmu;
110
+ if (viewportWidthEmu === void 0 || viewportHeightEmu === void 0) throw new Error(`Unsupported viewport ${errorContext} without viewport context: ${normalized}`);
111
+ const base = normalized.endsWith("vmin") ? Math.min(viewportWidthEmu, viewportHeightEmu) : Math.max(viewportWidthEmu, viewportHeightEmu);
112
+ const suffixLength = normalized.endsWith("vmin") ? 4 : 4;
113
+ return base * Number.parseFloat(normalized.slice(0, -suffixLength)) / 100;
114
+ }
115
+ }
79
116
  function isDeckLengthString(value) {
80
117
  return DECK_LENGTH_PATTERN.test(value.trim());
81
118
  }
82
119
  function isDeckPointLengthString(value) {
83
120
  return DECK_POINT_LENGTH_PATTERN.test(value.trim());
84
121
  }
122
+ function isCssWideKeyword(value) {
123
+ return typeof value === "string" && CSS_WIDE_KEYWORDS.has(value.trim().toLowerCase());
124
+ }
85
125
  function parseLengthToken(value, baseEmu, fallback = 0, context) {
86
126
  const trimmed = value.trim();
87
127
  if (trimmed === "0") return 0;
128
+ if (isCssWideKeyword(trimmed)) return fallback;
88
129
  if (!isDeckLengthString(trimmed)) throw new Error(`Unsupported length value: ${value}`);
89
130
  return parseLength(trimmed, baseEmu, fallback, context);
90
131
  }
91
132
  function parsePointToken(value, fallback = 0, context) {
92
133
  const trimmed = value.trim();
93
134
  if (trimmed === "0") return 0;
135
+ if (isCssWideKeyword(trimmed)) return fallback;
94
136
  if (!isDeckPointLengthString(trimmed)) throw new Error(`Unsupported point value: ${value}`);
95
137
  return parsePointValue(trimmed, fallback, context);
96
138
  }
97
139
  function parsePointValue(value, fallback = 0, context) {
98
140
  if (value === void 0) return fallback;
99
141
  if (typeof value === "number") return value;
100
- if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2));
101
- if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * 72;
102
- if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * 72;
103
- if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
104
- if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context);
105
- if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
106
- if (value.endsWith("vw")) {
107
- const viewportWidthEmu = context?.viewportWidthEmu;
108
- if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport point value without viewport context: ${value}`);
109
- return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
110
- }
111
- if (value.endsWith("vh")) {
112
- const viewportHeightEmu = context?.viewportHeightEmu;
113
- if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport point value without viewport context: ${value}`);
114
- return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
115
- }
142
+ const normalized = value.trim().toLowerCase();
143
+ if (normalized === "0") return 0;
144
+ if (isCssWideKeyword(normalized)) return fallback;
145
+ const absoluteInches = absoluteLengthInInches(normalized);
146
+ if (absoluteInches !== void 0) return absoluteInches * 72;
147
+ if (normalized.endsWith("rem")) return Number.parseFloat(normalized.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
148
+ if (normalized.endsWith("em")) return Number.parseFloat(normalized.slice(0, -2)) * resolvePointUnitBase(context);
149
+ if (normalized.endsWith("ch")) return Number.parseFloat(normalized.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
150
+ const viewportEmu = resolveViewportEmu(normalized, context, "point value");
151
+ if (viewportEmu !== void 0) return viewportEmu / EMU_PER_INCH * 72;
116
152
  throw new Error(`Unsupported point value: ${value}`);
117
153
  }
118
154
  function parseStrokeWidth(value, fallback = 0, context) {
119
155
  if (value === void 0) return fallback;
120
156
  if (typeof value === "number") return value;
121
- if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2));
122
- if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * 72;
123
- if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * 72;
124
- if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
125
- if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context);
126
- if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
127
- if (value.endsWith("vw")) {
128
- const viewportWidthEmu = context?.viewportWidthEmu;
129
- if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport stroke width without viewport context: ${value}`);
130
- return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
131
- }
132
- if (value.endsWith("vh")) {
133
- const viewportHeightEmu = context?.viewportHeightEmu;
134
- if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport stroke width without viewport context: ${value}`);
135
- return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100 / EMU_PER_INCH * 72;
136
- }
157
+ const normalized = value.trim().toLowerCase();
158
+ if (normalized === "0") return 0;
159
+ if (isCssWideKeyword(normalized)) return fallback;
160
+ const absoluteInches = absoluteLengthInInches(normalized);
161
+ if (absoluteInches !== void 0) return absoluteInches * 72;
162
+ if (normalized.endsWith("rem")) return Number.parseFloat(normalized.slice(0, -3)) * DEFAULT_FONT_SIZE_PT;
163
+ if (normalized.endsWith("em")) return Number.parseFloat(normalized.slice(0, -2)) * resolvePointUnitBase(context);
164
+ if (normalized.endsWith("ch")) return Number.parseFloat(normalized.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO;
165
+ const viewportEmu = resolveViewportEmu(normalized, context, "stroke width");
166
+ if (viewportEmu !== void 0) return viewportEmu / EMU_PER_INCH * 72;
137
167
  throw new Error(`Unsupported stroke width: ${value}`);
138
168
  }
139
169
  function parseLength(value, baseEmu, fallback = 0, context) {
140
170
  if (value === void 0) return fallback;
141
171
  if (typeof value === "number") return value * EMU_PER_INCH;
142
- if (value.endsWith("%")) return baseEmu * Number.parseFloat(value.slice(0, -1)) / 100;
143
- if (value.endsWith("in")) return Number.parseFloat(value.slice(0, -2)) * EMU_PER_INCH;
144
- if (value.endsWith("pt")) return Number.parseFloat(value.slice(0, -2)) / 72 * EMU_PER_INCH;
145
- if (value.endsWith("px")) return Number.parseFloat(value.slice(0, -2)) / 96 * EMU_PER_INCH;
146
- if (value.endsWith("rem")) return Number.parseFloat(value.slice(0, -3)) * DEFAULT_FONT_SIZE_PT * EMU_PER_INCH / 72;
147
- if (value.endsWith("em")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * EMU_PER_INCH / 72;
148
- if (value.endsWith("ch")) return Number.parseFloat(value.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO * EMU_PER_INCH / 72;
149
- if (value.endsWith("vw")) {
150
- const viewportWidthEmu = context?.viewportWidthEmu;
151
- if (viewportWidthEmu === void 0) throw new Error(`Unsupported viewport length without viewport context: ${value}`);
152
- return viewportWidthEmu * Number.parseFloat(value.slice(0, -2)) / 100;
153
- }
154
- if (value.endsWith("vh")) {
155
- const viewportHeightEmu = context?.viewportHeightEmu;
156
- if (viewportHeightEmu === void 0) throw new Error(`Unsupported viewport length without viewport context: ${value}`);
157
- return viewportHeightEmu * Number.parseFloat(value.slice(0, -2)) / 100;
158
- }
172
+ const normalized = value.trim().toLowerCase();
173
+ if (normalized === "0") return 0;
174
+ if (isCssWideKeyword(normalized)) return fallback;
175
+ if (normalized.endsWith("%")) return baseEmu * Number.parseFloat(normalized.slice(0, -1)) / 100;
176
+ const absoluteInches = absoluteLengthInInches(normalized);
177
+ if (absoluteInches !== void 0) return absoluteInches * EMU_PER_INCH;
178
+ if (normalized.endsWith("rem")) return Number.parseFloat(normalized.slice(0, -3)) * DEFAULT_FONT_SIZE_PT * EMU_PER_INCH / 72;
179
+ if (normalized.endsWith("em")) return Number.parseFloat(normalized.slice(0, -2)) * resolvePointUnitBase(context) * EMU_PER_INCH / 72;
180
+ if (normalized.endsWith("ch")) return Number.parseFloat(normalized.slice(0, -2)) * resolvePointUnitBase(context) * CH_WIDTH_RATIO * EMU_PER_INCH / 72;
181
+ const viewportEmu = resolveViewportEmu(normalized, context, "length");
182
+ if (viewportEmu !== void 0) return viewportEmu;
159
183
  throw new Error(`Unsupported length value: ${value}`);
160
184
  }
161
185
  //#endregion
@@ -458,7 +482,9 @@ const UNSUPPORTED_SEMANTIC_FEATURES = [
458
482
  "border",
459
483
  "clipping",
460
484
  "filter",
485
+ "image",
461
486
  "isolation",
487
+ "layout",
462
488
  "outline",
463
489
  "opacity",
464
490
  "shadow",
@@ -474,7 +500,8 @@ const UNSUPPORTED_FALLBACK_STRATEGIES = [
474
500
  "preserveAuthoredValueOnly",
475
501
  "preserveOpacityWithoutCompositedSubtree",
476
502
  "preserveTransformWithoutStackingContext",
477
- "sourceRectBeforeTransform"
503
+ "sourceRectBeforeTransform",
504
+ "synthesizeFallbackFrame"
478
505
  ];
479
506
  const THEME_VALUE_GROUPS = [
480
507
  "colorScheme",
@@ -539,7 +566,8 @@ const DRAWING_ELEMENT_KINDS = [
539
566
  "group",
540
567
  "image",
541
568
  "shape",
542
- "text"
569
+ "text",
570
+ "video"
543
571
  ];
544
572
  const DRAWING_VISIBILITIES = ["hidden", "visible"];
545
573
  const DRAWING_CLIP_STRATEGIES = ["intersectParentOverflow"];
@@ -651,6 +679,7 @@ const PACKAGE_PART_KINDS = [
651
679
  "slide",
652
680
  "slide-layout",
653
681
  "slide-master",
682
+ "table-styles",
654
683
  "theme",
655
684
  "view-properties"
656
685
  ];
@@ -667,6 +696,7 @@ const PACKAGE_PART_ORDER_GROUP_ORDERS = {
667
696
  slideLayoutRelationships: 71,
668
697
  viewProperties: 75,
669
698
  presentationProperties: 76,
699
+ tableStyles: 77,
670
700
  slide: 80,
671
701
  slideRelationships: 81,
672
702
  media: 90,
@@ -736,17 +766,21 @@ const CONTENT_TYPE_CORE_PROPERTIES = "application/vnd.openxmlformats-package.cor
736
766
  const CONTENT_TYPE_EXTENDED_PROPERTIES = "application/vnd.openxmlformats-officedocument.extended-properties+xml";
737
767
  const CONTENT_TYPE_VIEW_PROPERTIES = "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml";
738
768
  const CONTENT_TYPE_PRESENTATION_PROPERTIES = "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml";
769
+ const CONTENT_TYPE_TABLE_STYLES = "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml";
739
770
  const CONTENT_TYPE_NOTES_MASTER = "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml";
740
771
  const CONTENT_TYPE_NOTES_SLIDE = "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml";
741
772
  const INTERNAL_RELATIONSHIP_TARGET_KINDS = {
742
773
  coreProperties: ["document-properties"],
743
774
  extendedProperties: ["document-properties"],
744
775
  image: ["media"],
776
+ media: ["media"],
777
+ video: ["media"],
745
778
  officeDocument: ["presentation"],
746
779
  presentationProperties: ["presentation-properties"],
747
780
  slide: ["slide"],
748
781
  slideLayout: ["slide-layout"],
749
782
  slideMaster: ["slide-master"],
783
+ tableStyles: ["table-styles"],
750
784
  theme: ["theme"],
751
785
  viewProperties: ["view-properties"]
752
786
  };
@@ -755,6 +789,7 @@ const KNOWN_RELATIONSHIP_OWNER_TYPES = {
755
789
  "presentationProperties",
756
790
  "slide",
757
791
  "slideMaster",
792
+ "tableStyles",
758
793
  "theme",
759
794
  "viewProperties"
760
795
  ],
@@ -766,7 +801,9 @@ const KNOWN_RELATIONSHIP_OWNER_TYPES = {
766
801
  slide: [
767
802
  "hyperlink",
768
803
  "image",
769
- "slideLayout"
804
+ "media",
805
+ "slideLayout",
806
+ "video"
770
807
  ],
771
808
  slideLayout: ["slideMaster"],
772
809
  slideMaster: ["slideLayout", "theme"]
@@ -911,6 +948,20 @@ function mediaPayloadDiagnostic(input) {
911
948
  }]
912
949
  });
913
950
  }
951
+ function unsupportedVideoMediaDiagnostic(input) {
952
+ return diagnostic({
953
+ severity: "error",
954
+ code: "E_PROJECT_VIDEO_FORMAT_UNSUPPORTED",
955
+ title: "video format is not supported by the pptx projection",
956
+ message: "The initial pptx video compatibility target only accepts MP4 video media.",
957
+ labels: [{
958
+ path: input.path,
959
+ message: input.message
960
+ }],
961
+ notes: [input.mediaType ? `mediaType=${input.mediaType}` : void 0, input.extension ? `extension=${input.extension}` : void 0].filter((note) => note !== void 0),
962
+ help: ["Use video/mp4 media or an .mp4 source for the video tag."]
963
+ });
964
+ }
914
965
  function partRelationshipDiagnostic(input) {
915
966
  return diagnostic({
916
967
  severity: "error",
@@ -1024,6 +1075,29 @@ function validateDrawingFrame(input) {
1024
1075
  });
1025
1076
  return issues;
1026
1077
  }
1078
+ function validateDrawingFrameExtent(input) {
1079
+ const frame = input.element.frame;
1080
+ if (typeof frame !== "object" || frame === null) return [];
1081
+ const { widthEmu, heightEmu } = frame;
1082
+ if (typeof widthEmu !== "number" || typeof heightEmu !== "number" || !Number.isFinite(widthEmu) || !Number.isFinite(heightEmu)) return [];
1083
+ if (input.element.kind === "shape" && input.element.shape === "line") return widthEmu === 0 && heightEmu === 0 ? [drawingMetadataDiagnostic({
1084
+ path: `${input.path}.frame`,
1085
+ message: "line shape frame must have a non-zero axis",
1086
+ title: "pptx drawing frame is degenerate"
1087
+ })] : [];
1088
+ const issues = [];
1089
+ if (widthEmu === 0) issues.push(drawingMetadataDiagnostic({
1090
+ path: `${input.path}.frame.widthEmu`,
1091
+ message: "drawing frame width must be greater than zero",
1092
+ title: "pptx drawing frame is degenerate"
1093
+ }));
1094
+ if (heightEmu === 0) issues.push(drawingMetadataDiagnostic({
1095
+ path: `${input.path}.frame.heightEmu`,
1096
+ message: "drawing frame height must be greater than zero",
1097
+ title: "pptx drawing frame is degenerate"
1098
+ }));
1099
+ return issues;
1100
+ }
1027
1101
  function validateSlideLayoutAnchor(input) {
1028
1102
  const issues = [];
1029
1103
  if (typeof input.anchor.template !== "string" || input.anchor.template.length === 0) issues.push(diagnostic({
@@ -1269,6 +1343,29 @@ function validateEmptySupportPropertiesPayload(input) {
1269
1343
  }));
1270
1344
  return issues;
1271
1345
  }
1346
+ function validateTableStylesPayload(input) {
1347
+ const path = `projection.parts.${input.part.id}.payload`;
1348
+ const payload = input.part.payload;
1349
+ if (!isRecord(payload)) return [supportPayloadDiagnostic({
1350
+ path,
1351
+ message: "invalid table styles payload"
1352
+ })];
1353
+ const record = payload;
1354
+ const issues = [];
1355
+ if (record.kind !== "table-styles") issues.push(supportPayloadDiagnostic({
1356
+ path: `${path}.kind`,
1357
+ message: "expected table-styles payload"
1358
+ }));
1359
+ if (record.editable !== true) issues.push(supportPayloadDiagnostic({
1360
+ path: `${path}.editable`,
1361
+ message: "table styles payload must remain editable"
1362
+ }));
1363
+ if (typeof record.defaultStyleId !== "string" || record.defaultStyleId.length === 0) issues.push(supportPayloadDiagnostic({
1364
+ path: `${path}.defaultStyleId`,
1365
+ message: "table styles payload requires defaultStyleId"
1366
+ }));
1367
+ return issues;
1368
+ }
1272
1369
  function validateNotesPlaceholderPayload(input) {
1273
1370
  const path = `projection.parts.${input.part.id}.payload`;
1274
1371
  const payload = input.part.payload;
@@ -3236,6 +3333,44 @@ function validateDrawingElementPayload(input) {
3236
3333
  }));
3237
3334
  return issues;
3238
3335
  }
3336
+ if (element.kind === "video") {
3337
+ if (element.mediaPartId !== void 0 && typeof element.mediaPartId !== "string") issues.push(drawingPayloadDiagnostic({
3338
+ path: `${input.path}.mediaPartId`,
3339
+ message: "invalid media part id"
3340
+ }));
3341
+ if (element.posterMediaPartId !== void 0 && typeof element.posterMediaPartId !== "string") issues.push(drawingPayloadDiagnostic({
3342
+ path: `${input.path}.posterMediaPartId`,
3343
+ message: "invalid poster media part id"
3344
+ }));
3345
+ issues.push(...validateDrawingPayloadFrame({
3346
+ value: element.sourceFrame,
3347
+ path: `${input.path}.sourceFrame`,
3348
+ message: "invalid video source frame"
3349
+ }), ...validateDrawingImageSource({
3350
+ value: element.source,
3351
+ path: `${input.path}.source`
3352
+ }), ...element.posterSource ? validateDrawingImageSource({
3353
+ value: element.posterSource,
3354
+ path: `${input.path}.posterSource`
3355
+ }) : [], ...element.fit === "contain" || element.fit === "cover" || element.fit === "stretch" ? [] : [drawingPayloadDiagnostic({
3356
+ path: `${input.path}.fit`,
3357
+ message: "invalid video fit"
3358
+ })], ...validateDrawingObjectPosition({
3359
+ value: element.objectPosition,
3360
+ path: `${input.path}.objectPosition`
3361
+ }), ...validateOptionalDrawingTransparencyField({
3362
+ value: element.transparency,
3363
+ path: `${input.path}.transparency`,
3364
+ message: "invalid video transparency"
3365
+ }), ...element.rounding === void 0 || typeof element.rounding === "boolean" ? [] : [drawingPayloadDiagnostic({
3366
+ path: `${input.path}.rounding`,
3367
+ message: "invalid video rounding"
3368
+ })], ...validateDrawingShadow({
3369
+ value: element.shadow,
3370
+ path: `${input.path}.shadow`
3371
+ }));
3372
+ return issues;
3373
+ }
3239
3374
  if (element.kind === "shape") {
3240
3375
  if (element.shape !== "rect" && element.shape !== "ellipse" && element.shape !== "line") issues.push(drawingPayloadDiagnostic({
3241
3376
  path: `${input.path}.shape`,
@@ -3266,6 +3401,10 @@ function validateDrawingMetadata(input) {
3266
3401
  frame: input.element.frame,
3267
3402
  path: `${input.path}.frame`
3268
3403
  }),
3404
+ ...validateDrawingFrameExtent({
3405
+ element: input.element,
3406
+ path: input.path
3407
+ }),
3269
3408
  ...element.opacity === void 0 || typeof element.opacity === "number" && Number.isFinite(element.opacity) && element.opacity >= 0 && element.opacity <= 1 ? [] : [drawingMetadataDiagnostic({
3270
3409
  path: `${input.path}.opacity`,
3271
3410
  message: "invalid opacity"
@@ -3826,6 +3965,129 @@ function validateSlideImageRelationships(input) {
3826
3965
  partsById: input.partsById
3827
3966
  }));
3828
3967
  }
3968
+ if (element.kind === "video") {
3969
+ const issues = [];
3970
+ if (typeof element.mediaPartId !== "string" || element.mediaPartId.length === 0) {
3971
+ issues.push(slidePayloadDiagnostic({
3972
+ path: `${input.path}.mediaPartId`,
3973
+ message: "missing video media part id"
3974
+ }));
3975
+ return issues;
3976
+ }
3977
+ const relationshipId = isRecord(element.serialized) ? element.serialized.relationshipId : void 0;
3978
+ if (typeof relationshipId !== "string" || relationshipId.length === 0) {
3979
+ issues.push(slidePayloadDiagnostic({
3980
+ path: `${input.path}.serialized.relationshipId`,
3981
+ message: "missing video relationship id"
3982
+ }));
3983
+ return issues;
3984
+ }
3985
+ const relationship = relationshipRecords(input.slidePart).find((item) => item.id === relationshipId);
3986
+ if (!relationship) {
3987
+ issues.push(slidePayloadDiagnostic({
3988
+ path: `${input.path}.serialized.relationshipId`,
3989
+ message: `missing video relationship ${relationshipId}`
3990
+ }));
3991
+ return issues;
3992
+ }
3993
+ if (relationship.type !== "video") issues.push(slidePayloadDiagnostic({
3994
+ path: `${input.path}.serialized.relationshipId`,
3995
+ message: `relationship ${relationshipId} is not a video relationship`
3996
+ }));
3997
+ if (relationship.targetPartId !== element.mediaPartId) issues.push(slidePayloadDiagnostic({
3998
+ path: `${input.path}.mediaPartId`,
3999
+ message: `video media part id does not match relationship ${relationshipId}`
4000
+ }));
4001
+ const mediaPart = input.partsById.get(element.mediaPartId);
4002
+ if (!mediaPart) {
4003
+ issues.push(slidePayloadDiagnostic({
4004
+ path: `${input.path}.mediaPartId`,
4005
+ message: `missing media part ${element.mediaPartId}`
4006
+ }));
4007
+ return issues;
4008
+ }
4009
+ if (mediaPart.kind !== "media") issues.push(slidePayloadDiagnostic({
4010
+ path: `${input.path}.mediaPartId`,
4011
+ message: `video media part id targets ${mediaPart.kind}`
4012
+ }));
4013
+ if (relationship.targetPath && normalizedPartPath(relationship.targetPath) !== normalizedPartPath(mediaPart.path)) issues.push(slidePayloadDiagnostic({
4014
+ path: `${input.path}.serialized.relationshipId`,
4015
+ message: `video relationship ${relationshipId} target path does not match media part`
4016
+ }));
4017
+ const mediaRelationshipId = isRecord(element.serialized) ? element.serialized.mediaRelationshipId : void 0;
4018
+ if (typeof mediaRelationshipId !== "string" || mediaRelationshipId.length === 0) {
4019
+ issues.push(slidePayloadDiagnostic({
4020
+ path: `${input.path}.serialized.mediaRelationshipId`,
4021
+ message: "missing embedded media relationship id"
4022
+ }));
4023
+ return issues;
4024
+ }
4025
+ const mediaRelationship = relationshipRecords(input.slidePart).find((item) => item.id === mediaRelationshipId);
4026
+ if (!mediaRelationship) {
4027
+ issues.push(slidePayloadDiagnostic({
4028
+ path: `${input.path}.serialized.mediaRelationshipId`,
4029
+ message: `missing embedded media relationship ${mediaRelationshipId}`
4030
+ }));
4031
+ return issues;
4032
+ }
4033
+ if (mediaRelationship.type !== "media") issues.push(slidePayloadDiagnostic({
4034
+ path: `${input.path}.serialized.mediaRelationshipId`,
4035
+ message: `relationship ${mediaRelationshipId} is not an embedded media relationship`
4036
+ }));
4037
+ if (mediaRelationship.targetPartId !== element.mediaPartId) issues.push(slidePayloadDiagnostic({
4038
+ path: `${input.path}.mediaPartId`,
4039
+ message: `video media part id does not match embedded media relationship ${mediaRelationshipId}`
4040
+ }));
4041
+ if (!element.posterSource) {
4042
+ issues.push(slidePayloadDiagnostic({
4043
+ path: `${input.path}.posterSource`,
4044
+ message: "missing video poster source"
4045
+ }));
4046
+ return issues;
4047
+ }
4048
+ if (typeof element.posterMediaPartId !== "string" || element.posterMediaPartId.length === 0) {
4049
+ issues.push(slidePayloadDiagnostic({
4050
+ path: `${input.path}.posterMediaPartId`,
4051
+ message: "missing video poster media part id"
4052
+ }));
4053
+ return issues;
4054
+ }
4055
+ const posterPart = input.partsById.get(element.posterMediaPartId);
4056
+ if (!posterPart) {
4057
+ issues.push(slidePayloadDiagnostic({
4058
+ path: `${input.path}.posterMediaPartId`,
4059
+ message: `missing video poster media part ${element.posterMediaPartId}`
4060
+ }));
4061
+ return issues;
4062
+ }
4063
+ if (posterPart.kind !== "media") issues.push(slidePayloadDiagnostic({
4064
+ path: `${input.path}.posterMediaPartId`,
4065
+ message: `video poster media part id targets ${posterPart.kind}`
4066
+ }));
4067
+ const posterPayload = isRecord(posterPart.payload) ? posterPart.payload : void 0;
4068
+ if (posterPayload?.mediaKind !== void 0 && posterPayload.mediaKind !== "image") issues.push(slidePayloadDiagnostic({
4069
+ path: `${input.path}.posterMediaPartId`,
4070
+ message: "video poster media part id must target image media"
4071
+ }));
4072
+ const posterSourceKey = imageSourceKeyForValidation(element.posterSource);
4073
+ if (!(posterSourceKey ? mediaPartsBySourceKey(input.partsById).get(posterSourceKey) ?? [] : []).some((part) => part.id === element.posterMediaPartId)) issues.push(slidePayloadDiagnostic({
4074
+ path: `${input.path}.posterSource`,
4075
+ message: `video poster source does not match media part ${element.posterMediaPartId}`
4076
+ }));
4077
+ const posterRelationship = relationshipRecords(input.slidePart).find((item) => item.type === "image" && item.targetPartId === element.posterMediaPartId);
4078
+ if (!posterRelationship) {
4079
+ issues.push(slidePayloadDiagnostic({
4080
+ path: `${input.path}.posterMediaPartId`,
4081
+ message: `missing video poster image relationship to ${element.posterMediaPartId}`
4082
+ }));
4083
+ return issues;
4084
+ }
4085
+ if (posterRelationship.targetPath && normalizedPartPath(posterRelationship.targetPath) !== normalizedPartPath(posterPart.path)) issues.push(slidePayloadDiagnostic({
4086
+ path: `${input.path}.posterMediaPartId`,
4087
+ message: `video poster image relationship ${posterRelationship.id} target path does not match media part`
4088
+ }));
4089
+ return issues;
4090
+ }
3829
4091
  if (element.kind !== "image") return [];
3830
4092
  const issues = [];
3831
4093
  if (typeof element.mediaPartId !== "string" || element.mediaPartId.length === 0) {
@@ -4654,6 +4916,7 @@ function mediaContentTypeForExtension(extension) {
4654
4916
  case "png": return "image/png";
4655
4917
  case "gif": return "image/gif";
4656
4918
  case "svg": return "image/svg+xml";
4919
+ case "mp4": return "video/mp4";
4657
4920
  default: return "application/octet-stream";
4658
4921
  }
4659
4922
  }
@@ -4666,6 +4929,7 @@ function expectedOverrideContentType(part) {
4666
4929
  case "notes-slide": return CONTENT_TYPE_NOTES_SLIDE;
4667
4930
  case "presentation": return CONTENT_TYPE_PRESENTATION;
4668
4931
  case "presentation-properties": return CONTENT_TYPE_PRESENTATION_PROPERTIES;
4932
+ case "table-styles": return CONTENT_TYPE_TABLE_STYLES;
4669
4933
  case "slide": return CONTENT_TYPE_SLIDE;
4670
4934
  case "slide-layout": return CONTENT_TYPE_SLIDE_LAYOUT;
4671
4935
  case "slide-master": return CONTENT_TYPE_SLIDE_MASTER;
@@ -4987,6 +5251,15 @@ function validatePresentationRelationships(input) {
4987
5251
  type: "presentationProperties",
4988
5252
  targetPartId: candidate.id
4989
5253
  }));
5254
+ if (candidate.kind === "table-styles" && !relationshipExists(input.relationships, {
5255
+ type: "tableStyles",
5256
+ targetPartId: candidate.id
5257
+ })) issues.push(missingRequiredRelationshipDiagnostic({
5258
+ ownerPart: input.part,
5259
+ message: "Presentation relationships require a projected tableStyles relationship id.",
5260
+ type: "tableStyles",
5261
+ targetPartId: candidate.id
5262
+ }));
4990
5263
  });
4991
5264
  if (isPresentationPayload(input.part.payload)) input.part.payload.slidePartIds.forEach((slidePartId) => {
4992
5265
  if (!relationshipExists(input.relationships, {
@@ -5192,12 +5465,45 @@ function validatePrimarySourceInSources(input) {
5192
5465
  function mediaMetadataRecord(payload) {
5193
5466
  return isRecord(payload.metadata) ? payload.metadata : void 0;
5194
5467
  }
5468
+ function normalizedMetadataString(value) {
5469
+ return typeof value === "string" && value.length > 0 ? value.toLowerCase() : void 0;
5470
+ }
5471
+ function validateVideoMediaCompatibility(input) {
5472
+ if (input.payload.mediaKind !== "video") return [];
5473
+ const mediaType = normalizedMetadataString(input.metadata?.mediaType)?.split(";")[0]?.trim();
5474
+ const extension = normalizedMetadataString(input.metadata?.extension ?? input.pathExtension);
5475
+ const issues = [];
5476
+ if (mediaType !== void 0 && mediaType !== "video/mp4") issues.push(unsupportedVideoMediaDiagnostic({
5477
+ path: `${input.path}.metadata.mediaType`,
5478
+ message: "video media type is outside the initial pptx compatibility target",
5479
+ mediaType,
5480
+ ...extension ? { extension } : {}
5481
+ }));
5482
+ if (extension !== void 0 && extension !== "mp4") {
5483
+ const extensionPath = input.metadata?.extension !== void 0 ? `${input.path}.metadata.extension` : input.path.replace(/\.payload$/, ".path");
5484
+ issues.push(unsupportedVideoMediaDiagnostic({
5485
+ path: extensionPath,
5486
+ message: "video media extension is outside the initial pptx compatibility target",
5487
+ ...mediaType ? { mediaType } : {},
5488
+ extension
5489
+ }));
5490
+ }
5491
+ if (mediaType === void 0 && extension === void 0) issues.push(unsupportedVideoMediaDiagnostic({
5492
+ path: input.path,
5493
+ message: "video media type and extension could not be inferred"
5494
+ }));
5495
+ return issues;
5496
+ }
5195
5497
  function validateMediaPayloadConsistency(input) {
5196
5498
  const path = `projection.parts.${input.part.id}.payload`;
5197
5499
  const metadata = mediaMetadataRecord(input.payload);
5198
5500
  const issues = [];
5199
5501
  const pathExtension = packagePartExtension(input.part);
5200
5502
  const metadataExtension = metadata?.extension;
5503
+ if (input.payload.mediaKind !== void 0 && input.payload.mediaKind !== "image" && input.payload.mediaKind !== "video") issues.push(mediaPayloadDiagnostic({
5504
+ path: `${path}.mediaKind`,
5505
+ message: "invalid media kind"
5506
+ }));
5201
5507
  if (pathExtension && typeof metadataExtension === "string" && metadataExtension.toLowerCase() !== pathExtension) issues.push(mediaPayloadDiagnostic({
5202
5508
  path: `${path}.metadata.extension`,
5203
5509
  message: `media metadata extension does not match package path extension ${pathExtension}`
@@ -5211,7 +5517,7 @@ function validateMediaPayloadConsistency(input) {
5211
5517
  }
5212
5518
  if (typeof metadata?.hash === "string" && metadata.hash.length > 0) {
5213
5519
  const allocationKey = input.payload.allocationKey;
5214
- if (typeof allocationKey === "string" && allocationKey.length > 0 && !allocationKey.startsWith(`hash:${metadata.hash}:`)) issues.push(mediaPayloadDiagnostic({
5520
+ if (typeof allocationKey === "string" && allocationKey.length > 0 && !allocationKey.startsWith(`hash:${metadata.hash}:`) && !allocationKey.startsWith(`${input.payload.mediaKind ?? "image"}:hash:${metadata.hash}:`)) issues.push(mediaPayloadDiagnostic({
5215
5521
  path: `${path}.allocationKey`,
5216
5522
  message: "media allocation key does not include metadata hash"
5217
5523
  }));
@@ -5235,6 +5541,12 @@ function validateMediaPayloadConsistency(input) {
5235
5541
  values: input.payload.assetEntityIds,
5236
5542
  label: "media asset id"
5237
5543
  }));
5544
+ issues.push(...validateVideoMediaCompatibility({
5545
+ path,
5546
+ pathExtension,
5547
+ payload: input.payload,
5548
+ metadata
5549
+ }));
5238
5550
  return issues;
5239
5551
  }
5240
5552
  function validateMediaPayload(input) {
@@ -5364,7 +5676,7 @@ function isPackagePartRequirementCondition(value) {
5364
5676
  return value === "explicit" || value === "hasRelationships" || value === "minimalPackage" || value === "referencedByRelationship";
5365
5677
  }
5366
5678
  function isPackagePartOrderGroup(value) {
5367
- return value === "contentTypes" || value === "documentProperties" || value === "media" || value === "other" || value === "presentation" || value === "presentationProperties" || value === "presentationRelationships" || value === "rootRelationships" || value === "slide" || value === "slideLayout" || value === "slideLayoutRelationships" || value === "slideMaster" || value === "slideMasterRelationships" || value === "slideRelationships" || value === "theme" || value === "viewProperties";
5679
+ return value === "contentTypes" || value === "documentProperties" || value === "media" || value === "other" || value === "presentation" || value === "presentationProperties" || value === "presentationRelationships" || value === "rootRelationships" || value === "slide" || value === "slideLayout" || value === "slideLayoutRelationships" || value === "slideMaster" || value === "slideMasterRelationships" || value === "slideRelationships" || value === "tableStyles" || value === "theme" || value === "viewProperties";
5368
5680
  }
5369
5681
  function expectedPackagePartOrderGroup(part) {
5370
5682
  const path = normalizedPartPath(part.path);
@@ -5380,6 +5692,7 @@ function expectedPackagePartOrderGroup(part) {
5380
5692
  if (part.kind === "relationships" && path.startsWith("ppt/slideLayouts/_rels/")) return "slideLayoutRelationships";
5381
5693
  if (part.kind === "view-properties") return "viewProperties";
5382
5694
  if (part.kind === "presentation-properties") return "presentationProperties";
5695
+ if (part.kind === "table-styles") return "tableStyles";
5383
5696
  if (part.kind === "slide") return "slide";
5384
5697
  if (part.kind === "relationships" && path.startsWith("ppt/slides/_rels/")) return "slideRelationships";
5385
5698
  if (part.kind === "media") return "media";
@@ -5879,6 +6192,7 @@ function expectedPackagePartPathFamily(part) {
5879
6192
  case "notes-slide": return NOTES_SLIDE_PART_PATH_PATTERN.test(path) ? void 0 : "ppt/notesSlides/notesSlideN.xml";
5880
6193
  case "presentation": return path === "ppt/presentation.xml" ? void 0 : "ppt/presentation.xml";
5881
6194
  case "presentation-properties": return path === "ppt/presProps.xml" ? void 0 : "ppt/presProps.xml";
6195
+ case "table-styles": return path === "ppt/tableStyles.xml" ? void 0 : "ppt/tableStyles.xml";
5882
6196
  case "relationships": return RELATIONSHIPS_PART_PATH_PATTERNS.some((pattern) => pattern.test(path)) ? void 0 : "_rels/.rels or known ppt/*/_rels/*.xml.rels";
5883
6197
  case "slide": return SLIDE_PART_PATH_PATTERN.test(path) ? void 0 : "ppt/slides/slideN.xml";
5884
6198
  case "slide-layout": return SLIDE_LAYOUT_PART_PATH_PATTERN.test(path) ? void 0 : "ppt/slideLayouts/slideLayoutN.xml";
@@ -6227,6 +6541,7 @@ function validatePptxPackageConsistency(projection) {
6227
6541
  expectedSlideCount: presentationSlideCount
6228
6542
  }));
6229
6543
  if (part.kind === "view-properties" || part.kind === "presentation-properties") issues.push(...validateEmptySupportPropertiesPayload({ part }));
6544
+ if (part.kind === "table-styles") issues.push(...validateTableStylesPayload({ part }));
6230
6545
  if (part.kind === "notes-master" || part.kind === "notes-slide") issues.push(...validateNotesPlaceholderPayload({ part }));
6231
6546
  if (part.kind === "theme" && isThemePayload(part.payload)) issues.push(...validateThemePayload({
6232
6547
  part,
@@ -6529,6 +6844,7 @@ const PPTX_EMITTER_FINGERPRINTS = {
6529
6844
  slide: "deckjsx:pptx-emitter:slide:0.8-generated-strokes",
6530
6845
  "slide-layout": "deckjsx:pptx-emitter:slide-layout:0.8-chunk-skeleton",
6531
6846
  "slide-master": "deckjsx:pptx-emitter:slide-master:0.8-chunk-skeleton",
6847
+ "table-styles": "deckjsx:pptx-emitter:table-styles:0.8-bootstrap",
6532
6848
  theme: "deckjsx:pptx-emitter:theme:0.8-bootstrap",
6533
6849
  "view-properties": "deckjsx:pptx-emitter:view-properties:0.8-bootstrap"
6534
6850
  };
@@ -6717,12 +7033,15 @@ const RELATIONSHIP_TYPES = {
6717
7033
  coreProperties: "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
6718
7034
  extendedProperties: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
6719
7035
  image: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
7036
+ media: "http://schemas.microsoft.com/office/2007/relationships/media",
7037
+ video: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/video",
6720
7038
  hyperlink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
6721
7039
  officeDocument: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
6722
7040
  presentationProperties: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/presProps",
6723
7041
  slide: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide",
6724
7042
  slideLayout: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout",
6725
7043
  slideMaster: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster",
7044
+ tableStyles: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/tableStyles",
6726
7045
  theme: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
6727
7046
  viewProperties: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/viewProps"
6728
7047
  };
@@ -6884,14 +7203,37 @@ function presentationBytes(part, projection) {
6884
7203
  })
6885
7204
  });
6886
7205
  });
6887
- return writer.close("p:sldIdLst").empty("p:sldSz", {
7206
+ writer.close("p:sldIdLst").empty("p:sldSz", {
6888
7207
  cx: emu$1(size.widthEmu, "presentation.size.widthEmu"),
6889
7208
  cy: emu$1(size.heightEmu, "presentation.size.heightEmu"),
6890
- type: "custom"
7209
+ type: size.widthEmu === 9144e3 && size.heightEmu === 5143500 ? "screen16x9" : "custom"
6891
7210
  }).empty("p:notesSz", {
6892
7211
  cx: emu$1(size.widthEmu, "presentation.size.widthEmu"),
6893
7212
  cy: emu$1(size.heightEmu, "presentation.size.heightEmu")
6894
- }).close("p:presentation").bytes();
7213
+ }).open("p:defaultTextStyle").open("a:defPPr").empty("a:defRPr").close("a:defPPr");
7214
+ for (let level = 1; level <= 9; level += 1) writer.open(`a:lvl${level}pPr`, {
7215
+ marL: (level - 1) * 457200,
7216
+ algn: "l",
7217
+ defTabSz: 914400,
7218
+ rtl: 0,
7219
+ eaLnBrk: 1,
7220
+ latinLnBrk: 0,
7221
+ hangingPunct: 1
7222
+ }).open("a:defRPr", {
7223
+ kumimoji: 1,
7224
+ sz: 1800,
7225
+ kern: 1200
7226
+ }).open("a:solidFill").empty("a:schemeClr", { val: "tx1" }).close("a:solidFill").empty("a:latin", { typeface: "+mn-lt" }).empty("a:ea", { typeface: "+mn-ea" }).empty("a:cs", { typeface: "+mn-cs" }).close("a:defRPr").close(`a:lvl${level}pPr`);
7227
+ return writer.close("p:defaultTextStyle").close("p:presentation").bytes();
7228
+ }
7229
+ function tableStylesXml(part) {
7230
+ return new TextDecoder().decode(tableStylesBytes(part));
7231
+ }
7232
+ function tableStylesBytes(part) {
7233
+ return new XmlChunkWriter().declaration().empty("a:tblStyleLst", {
7234
+ "xmlns:a": DRAWING_ML_NS$1,
7235
+ def: part.payload.defaultStyleId
7236
+ }).bytes();
6895
7237
  }
6896
7238
  function themeXml(part) {
6897
7239
  return new TextDecoder().decode(themeBytes(part));
@@ -6908,6 +7250,32 @@ function requireThemeColor(payload, key) {
6908
7250
  if (typeof value !== "string" || !PROJECTED_RGB_COLOR_PATTERN.test(value)) throw new Error(`Theme support payload must include valid colorScheme.colors.${key}.`);
6909
7251
  return value;
6910
7252
  }
7253
+ function schemeFill(writer, transforms = []) {
7254
+ writer.open("a:solidFill").open("a:schemeClr", { val: "phClr" });
7255
+ transforms.forEach((transform) => {
7256
+ writer.empty(`a:${transform.name}`, { val: transform.val });
7257
+ });
7258
+ writer.close("a:schemeClr").close("a:solidFill");
7259
+ }
7260
+ function themeLineStyle(writer, width) {
7261
+ writer.open("a:ln", {
7262
+ w: width,
7263
+ cap: "flat",
7264
+ cmpd: "sng",
7265
+ algn: "ctr"
7266
+ }).open("a:solidFill").empty("a:schemeClr", { val: "phClr" }).close("a:solidFill").empty("a:prstDash", { val: "solid" }).empty("a:miter", { lim: 8e5 }).close("a:ln");
7267
+ }
7268
+ function themeEffectStyle(writer, shadow) {
7269
+ writer.open("a:effectStyle").open("a:effectLst");
7270
+ if (shadow) writer.open("a:outerShdw", {
7271
+ blurRad: 57150,
7272
+ dist: 19050,
7273
+ dir: 54e5,
7274
+ algn: "ctr",
7275
+ rotWithShape: 0
7276
+ }).open("a:srgbClr", { val: "000000" }).empty("a:alpha", { val: 63e3 }).close("a:srgbClr").close("a:outerShdw");
7277
+ writer.close("a:effectLst").close("a:effectStyle");
7278
+ }
6911
7279
  function themeBytes(part) {
6912
7280
  const payload = part.payload;
6913
7281
  const writer = new XmlChunkWriter().declaration().open("a:theme", {
@@ -6915,7 +7283,47 @@ function themeBytes(part) {
6915
7283
  name: requireThemeText(payload.name, "name")
6916
7284
  }).open("a:themeElements").open("a:clrScheme", { name: requireThemeText(payload.colorScheme.name, "colorScheme.name") });
6917
7285
  for (const name of THEME_COLOR_KEYS) themeColor(writer, name, requireThemeColor(payload, name));
6918
- return writer.close("a:clrScheme").open("a:fontScheme", { name: requireThemeText(payload.fontScheme.name, "fontScheme.name") }).open("a:majorFont").empty("a:latin", { typeface: requireThemeText(payload.fontScheme.majorLatin, "fontScheme.majorLatin") }).close("a:majorFont").open("a:minorFont").empty("a:latin", { typeface: requireThemeText(payload.fontScheme.minorLatin, "fontScheme.minorLatin") }).close("a:minorFont").close("a:fontScheme").open("a:fmtScheme", { name: requireThemeText(payload.formatScheme.name, "formatScheme.name") }).open("a:fillStyleLst").open("a:solidFill").empty("a:schemeClr", { val: "phClr" }).close("a:solidFill").close("a:fillStyleLst").open("a:lnStyleLst").open("a:ln", { w: 9525 }).open("a:solidFill").empty("a:schemeClr", { val: "phClr" }).close("a:solidFill").close("a:ln").close("a:lnStyleLst").open("a:effectStyleLst").open("a:effectStyle").empty("a:effectLst").close("a:effectStyle").close("a:effectStyleLst").open("a:bgFillStyleLst").open("a:solidFill").empty("a:schemeClr", { val: "phClr" }).close("a:solidFill").close("a:bgFillStyleLst").close("a:fmtScheme").close("a:themeElements").empty("a:objectDefaults").empty("a:extraClrSchemeLst").close("a:theme").bytes();
7286
+ writer.close("a:clrScheme").open("a:fontScheme", { name: requireThemeText(payload.fontScheme.name, "fontScheme.name") }).open("a:majorFont").empty("a:latin", { typeface: requireThemeText(payload.fontScheme.majorLatin, "fontScheme.majorLatin") }).empty("a:ea", { typeface: "" }).empty("a:cs", { typeface: "" }).close("a:majorFont").open("a:minorFont").empty("a:latin", { typeface: requireThemeText(payload.fontScheme.minorLatin, "fontScheme.minorLatin") }).empty("a:ea", { typeface: "" }).empty("a:cs", { typeface: "" }).close("a:minorFont").close("a:fontScheme").open("a:fmtScheme", { name: requireThemeText(payload.formatScheme.name, "formatScheme.name") }).open("a:fillStyleLst");
7287
+ schemeFill(writer);
7288
+ schemeFill(writer, [{
7289
+ name: "tint",
7290
+ val: 67e3
7291
+ }, {
7292
+ name: "satMod",
7293
+ val: 105e3
7294
+ }]);
7295
+ schemeFill(writer, [{
7296
+ name: "shade",
7297
+ val: 78e3
7298
+ }, {
7299
+ name: "satMod",
7300
+ val: 12e4
7301
+ }]);
7302
+ writer.close("a:fillStyleLst").open("a:lnStyleLst");
7303
+ themeLineStyle(writer, 12700);
7304
+ themeLineStyle(writer, 19050);
7305
+ themeLineStyle(writer, 25400);
7306
+ writer.close("a:lnStyleLst").open("a:effectStyleLst");
7307
+ themeEffectStyle(writer, false);
7308
+ themeEffectStyle(writer, false);
7309
+ themeEffectStyle(writer, true);
7310
+ writer.close("a:effectStyleLst").open("a:bgFillStyleLst");
7311
+ schemeFill(writer);
7312
+ schemeFill(writer, [{
7313
+ name: "tint",
7314
+ val: 95e3
7315
+ }, {
7316
+ name: "satMod",
7317
+ val: 17e4
7318
+ }]);
7319
+ schemeFill(writer, [{
7320
+ name: "shade",
7321
+ val: 63e3
7322
+ }, {
7323
+ name: "satMod",
7324
+ val: 12e4
7325
+ }]);
7326
+ return writer.close("a:bgFillStyleLst").close("a:fmtScheme").close("a:themeElements").empty("a:objectDefaults").empty("a:extraClrSchemeLst").close("a:theme").bytes();
6919
7327
  }
6920
7328
  function emptyShapeTree(writer) {
6921
7329
  return writer.open("p:spTree").open("p:nvGrpSpPr").empty("p:cNvPr", {
@@ -7058,6 +7466,7 @@ function supportPayloadMessage(part) {
7058
7466
  case "presentation-properties": return "presentation-properties parts must carry a structured presentation-properties payload.";
7059
7467
  case "slide-layout": return "Slide layout support parts must carry a structured slide-layout payload.";
7060
7468
  case "slide-master": return "Slide master support parts must carry a structured slide-master payload.";
7469
+ case "table-styles": return "table-styles parts must carry a structured table-styles payload.";
7061
7470
  case "theme": return "Theme support parts must carry a structured theme payload.";
7062
7471
  case "view-properties": return "view-properties parts must carry a structured view-properties payload.";
7063
7472
  case "notes-master": return "notes-master support parts must carry a structured notes-master payload.";
@@ -7102,6 +7511,10 @@ function partXml(part, projection, emitters) {
7102
7511
  const supportPart = requireSupportPart(part);
7103
7512
  return supportPart.kind === "presentation-properties" ? emptyPresentationPropertiesXml(supportPart, "presentation-properties") : void 0;
7104
7513
  }
7514
+ case "table-styles": {
7515
+ const supportPart = requireSupportPart(part);
7516
+ return supportPart.kind === "table-styles" ? tableStylesXml(supportPart) : void 0;
7517
+ }
7105
7518
  case "media":
7106
7519
  case "notes-master":
7107
7520
  case "notes-slide": return;
@@ -7144,6 +7557,10 @@ function emitPartBytes(part, projection, emitters) {
7144
7557
  const supportPart = requireSupportPart(part);
7145
7558
  return supportPart.kind === "presentation-properties" ? emptyPresentationPropertiesBytes(supportPart, "presentation-properties") : void 0;
7146
7559
  }
7560
+ case "table-styles": {
7561
+ const supportPart = requireSupportPart(part);
7562
+ return supportPart.kind === "table-styles" ? tableStylesBytes(supportPart) : void 0;
7563
+ }
7147
7564
  default: {
7148
7565
  const content = partXml(part, projection, emitters);
7149
7566
  return content ? encodeXml(content) : void 0;
@@ -7409,11 +7826,14 @@ function requireProjectedRelationshipId(relationshipId, input) {
7409
7826
  if (!relationshipId) throw new Error(`${input.label} must reference projected ${input.type} relationship id.`);
7410
7827
  return relationshipId;
7411
7828
  }
7412
- function writeNonVisual(writer, kind, id, name, hyperlinkRelationshipId, hyperlinkTooltip) {
7829
+ function writerShapeObjectNumericId(id, name) {
7413
7830
  if (typeof id !== "string" || !/^[1-9]\d*$/.test(id)) throw new Error(`${name} must carry a projected positive shape object id.`);
7414
7831
  const objectId = Number.parseInt(id, 10);
7415
7832
  if (!Number.isSafeInteger(objectId) || objectId <= 0 || objectId > MAX_WRITER_SHAPE_OBJECT_ID) throw new Error(`${name} must carry a projected positive shape object id.`);
7416
- const numericId = objectId + 1;
7833
+ return objectId + 1;
7834
+ }
7835
+ function writeNonVisual(writer, kind, id, name, hyperlinkRelationshipId, hyperlinkTooltip) {
7836
+ const numericId = writerShapeObjectNumericId(id, name);
7417
7837
  if (kind === "pic") {
7418
7838
  writer.open("p:nvPicPr").open("p:cNvPr", {
7419
7839
  id: numericId,
@@ -8096,6 +8516,54 @@ function hyperlinkRelationshipIdFor(element, context) {
8096
8516
  type: "hyperlink"
8097
8517
  }) : void 0;
8098
8518
  }
8519
+ function videoShapeObjectId(element, index) {
8520
+ return writerShapeObjectNumericId(element.serialized.shapeObjectId, `Video ${index}`);
8521
+ }
8522
+ function writeVideoNonVisual(writer, element, index, videoRelationshipId, mediaRelationshipId) {
8523
+ writer.open("p:nvPicPr").open("p:cNvPr", {
8524
+ id: videoShapeObjectId(element, index),
8525
+ name: `Video ${index}`
8526
+ }).close("p:cNvPr").open("p:cNvPicPr").empty("a:picLocks", { noChangeAspect: 1 }).close("p:cNvPicPr").open("p:nvPr").empty("a:videoFile", { "r:link": videoRelationshipId }).open("p:extLst").open("p:ext", { uri: "{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}" }).empty("p14:media", {
8527
+ "xmlns:p14": "http://schemas.microsoft.com/office/powerpoint/2010/main",
8528
+ "r:embed": mediaRelationshipId
8529
+ }).close("p:ext").close("p:extLst").close("p:nvPr").close("p:nvPicPr");
8530
+ }
8531
+ function writeVideoElement(writer, element, index, inheritedOpacity, context) {
8532
+ const videoRelationshipId = requireSlideRelationshipId(element.serialized.relationshipId, {
8533
+ context,
8534
+ label: `Video drawing element ${element.id}`,
8535
+ type: "video"
8536
+ });
8537
+ const mediaRelationshipId = requireSlideRelationshipId(element.serialized.mediaRelationshipId, {
8538
+ context,
8539
+ label: `Video drawing element ${element.id}`,
8540
+ type: "media"
8541
+ });
8542
+ const posterSource = element.posterSource;
8543
+ if (!posterSource) throw new Error(`Video drawing element ${element.id} requires a projected poster source.`);
8544
+ const posterRelationshipId = requireSlideRelationshipId(context.mediaRelationshipBySource.get(imageSourceKey(posterSource)), {
8545
+ context,
8546
+ label: `Video poster drawing element ${element.id}`,
8547
+ type: "image"
8548
+ });
8549
+ const transparency = alphaValue(element.transparency, combineOpacity(inheritedOpacity, element.opacity));
8550
+ writer.open("p:pic");
8551
+ writeVideoNonVisual(writer, element, index, videoRelationshipId, mediaRelationshipId);
8552
+ writer.open("p:blipFill").open("a:blip", { "r:embed": posterRelationshipId });
8553
+ if (transparency !== void 0 && transparency !== 1e5) writer.empty("a:alphaModFix", { amt: transparency });
8554
+ writer.close("a:blip");
8555
+ writeSrcRect(writer, resolveImageSrcRect({
8556
+ ...element,
8557
+ source: posterSource,
8558
+ fit: "stretch"
8559
+ }, context, "Video poster"));
8560
+ writer.close("p:blipFill");
8561
+ writer.open("p:spPr");
8562
+ writeTransform(writer, element.frame, element.rotation, element.flipH, element.flipV);
8563
+ writer.open("a:prstGeom", { prst: element.rounding ? "roundRect" : "rect" }).empty("a:avLst").close("a:prstGeom");
8564
+ writeShadow(writer, element.shadow);
8565
+ writer.close("p:spPr").close("p:pic");
8566
+ }
8099
8567
  function writeTextElement(writer, element, index, inheritedOpacity, context) {
8100
8568
  const opacity = combineOpacity(inheritedOpacity, element.opacity);
8101
8569
  const hyperlinkRelationshipId = hyperlinkRelationshipIdFor(element, context);
@@ -8202,6 +8670,9 @@ function writeDrawingElement(writer, element, index, inheritedOpacity, context)
8202
8670
  case "image":
8203
8671
  writePictureElement(writer, element, index, context, inheritedOpacity);
8204
8672
  return;
8673
+ case "video":
8674
+ writeVideoElement(writer, element, index, inheritedOpacity, context);
8675
+ return;
8205
8676
  case "shape":
8206
8677
  writeShapeElement(writer, element, index, inheritedOpacity, context);
8207
8678
  return;
@@ -8610,4 +9081,4 @@ function pptx(options = {}) {
8610
9081
  };
8611
9082
  }
8612
9083
  //#endregion
8613
- export { CompositionDiagnosticError as A, parsePointValue as C, POINTS_PER_INCH as D, EMU_PER_INCH as E, formatDiagnostics as F, SemanticGraphDiagnosticError as M, StyleDiagnosticError as N, createDiagnostics as O, formatDiagnostic as P, parsePointToken as S, pointsToEmu as T, isDeckLengthString as _, isInspectableThemePayload as a, parseLengthToken as b, fingerprintString as c, createWriterRenderContext as d, createTemplateHandle as f, DEFAULT_FONT_SIZE_PT as g, validateSlideTemplates as h, isContentTypesPayload as i, DeckDiagnosticError as j, diagnostic as k, stableJson$1 as l, templateRefValue as m, pptxMediaAssetLoadRequirements as n, isRecord as o, isTemplateAreaRef as p, validatePptxPackageModel as r, projectedRelationshipTarget as s, pptx as t, withPackagePartFingerprints as u, isDeckPointLengthString as v, parseStrokeWidth as w, parsePercentage as x, parseLength as y };
9084
+ export { diagnostic as A, parsePointToken as C, EMU_PER_INCH as D, pointsToEmu as E, formatDiagnostic as F, formatDiagnostics as I, DeckDiagnosticError as M, SemanticGraphDiagnosticError as N, POINTS_PER_INCH as O, StyleDiagnosticError as P, parsePercentage as S, parseStrokeWidth as T, isCssWideKeyword as _, isInspectableThemePayload as a, parseLength as b, fingerprintString as c, createWriterRenderContext as d, createTemplateHandle as f, DEFAULT_FONT_SIZE_PT as g, validateSlideTemplates as h, isContentTypesPayload as i, CompositionDiagnosticError as j, createDiagnostics as k, stableJson$1 as l, templateRefValue as m, pptxMediaAssetLoadRequirements as n, isRecord as o, isTemplateAreaRef as p, validatePptxPackageModel as r, projectedRelationshipTarget as s, pptx as t, withPackagePartFingerprints as u, isDeckLengthString as v, parsePointValue as w, parseLengthToken as x, isDeckPointLengthString as y };