ppt-codec 1.5.0 → 1.7.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.
Files changed (74) hide show
  1. package/README.md +91 -75
  2. package/dist/base64.cjs +48 -0
  3. package/dist/base64.d.cts +5 -0
  4. package/dist/base64.d.ts +5 -0
  5. package/dist/base64.js +46 -0
  6. package/dist/diagnostics-CqxAnubw.d.cts +16 -0
  7. package/dist/diagnostics-CqxAnubw.d.ts +16 -0
  8. package/dist/diagnostics.cjs +11 -0
  9. package/dist/diagnostics.d.cts +2 -0
  10. package/dist/diagnostics.d.ts +2 -0
  11. package/dist/diagnostics.js +9 -0
  12. package/dist/document/color-scheme.cjs +4 -0
  13. package/dist/document/color-scheme.d.cts +2 -1
  14. package/dist/document/color-scheme.d.ts +2 -1
  15. package/dist/document/color-scheme.js +4 -1
  16. package/dist/document/master-write.cjs +21 -16
  17. package/dist/document/master-write.d.cts +2 -1
  18. package/dist/document/master-write.d.ts +2 -1
  19. package/dist/document/master-write.js +21 -16
  20. package/dist/document/notes-write.cjs +15 -7
  21. package/dist/document/notes-write.d.cts +2 -1
  22. package/dist/document/notes-write.d.ts +2 -1
  23. package/dist/document/notes-write.js +15 -7
  24. package/dist/document/notes.cjs +4 -3
  25. package/dist/document/notes.js +4 -3
  26. package/dist/drawing/blips.cjs +81 -0
  27. package/dist/drawing/blips.d.cts +16 -0
  28. package/dist/drawing/blips.d.ts +16 -0
  29. package/dist/drawing/blips.js +77 -0
  30. package/dist/drawing/properties.cjs +102 -0
  31. package/dist/drawing/properties.d.cts +29 -0
  32. package/dist/drawing/properties.d.ts +29 -0
  33. package/dist/drawing/properties.js +87 -0
  34. package/dist/drawing/shapes-write.cjs +234 -17
  35. package/dist/drawing/shapes-write.d.cts +16 -4
  36. package/dist/drawing/shapes-write.d.ts +16 -4
  37. package/dist/drawing/shapes-write.js +237 -19
  38. package/dist/drawing/shapes.cjs +34 -4
  39. package/dist/drawing/shapes.d.cts +11 -2
  40. package/dist/drawing/shapes.d.ts +11 -2
  41. package/dist/drawing/shapes.js +35 -5
  42. package/dist/index.cjs +48 -3
  43. package/dist/index.d.cts +12 -8
  44. package/dist/index.d.ts +12 -8
  45. package/dist/index.js +11 -7
  46. package/dist/ole/embedded-write.cjs +66 -0
  47. package/dist/ole/embedded-write.d.cts +12 -0
  48. package/dist/ole/embedded-write.d.ts +12 -0
  49. package/dist/ole/embedded-write.js +63 -0
  50. package/dist/ole/embedded.cjs +66 -0
  51. package/dist/ole/embedded.d.cts +12 -0
  52. package/dist/ole/embedded.d.ts +12 -0
  53. package/dist/ole/embedded.js +63 -0
  54. package/dist/read.cjs +145 -22
  55. package/dist/read.d.cts +13 -5
  56. package/dist/read.d.ts +13 -5
  57. package/dist/read.js +148 -26
  58. package/dist/record/types.cjs +28 -0
  59. package/dist/record/types.d.cts +15 -1
  60. package/dist/record/types.d.ts +15 -1
  61. package/dist/record/types.js +15 -1
  62. package/dist/stream/current-user.cjs +1 -0
  63. package/dist/stream/current-user.d.cts +2 -1
  64. package/dist/stream/current-user.d.ts +2 -1
  65. package/dist/stream/current-user.js +1 -1
  66. package/dist/units.cjs +10 -0
  67. package/dist/units.d.cts +4 -1
  68. package/dist/units.d.ts +4 -1
  69. package/dist/units.js +8 -1
  70. package/dist/write.cjs +137 -38
  71. package/dist/write.d.cts +14 -5
  72. package/dist/write.d.ts +14 -5
  73. package/dist/write.js +137 -38
  74. package/package.json +2 -1
@@ -1,10 +1,38 @@
1
- import { OfficeArtClientAnchor, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtFSP, OfficeArtFSPGR, OfficeArtSpContainer, OfficeArtSpgrContainer, RT_Drawing, RT_TextCharsAtom, RT_TextHeaderAtom } from "../record/types.js";
1
+ import { PptUnsupportedContentError } from "../errors.js";
2
+ import { OfficeArtChildAnchor, OfficeArtClientAnchor, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtFOPT, OfficeArtFSP, OfficeArtFSPGR, OfficeArtSpContainer, OfficeArtSpgrContainer, OfficeArtTertiaryFOPT, RT_Drawing, RT_TextCharsAtom, RT_TextHeaderAtom } from "../record/types.js";
2
3
  import { characterCountOf } from "../text/atoms.js";
3
- import { pointsToMasterUnits } from "../units.js";
4
+ import { pointsToEmu, pointsToMasterUnits } from "../units.js";
4
5
  import { buildTextBody } from "../content-write.js";
6
+ import { PptDiagnosticCodes } from "../diagnostics.js";
5
7
  import { concatBytes, i32le, u32le, utf16le, writeAtom, writeContainer } from "../record/write.js";
8
+ import { isBlipFormat } from "./blips.js";
9
+ import { degreesToFixedPoint, writeIMsoArray, writeShapePropertyTable } from "./properties.js";
10
+ import { DEFAULT_INSET_LEFT_RIGHT_PT, DEFAULT_INSET_TOP_BOTTOM_PT } from "../read.js";
6
11
  import { writeStyleTextPropAtom } from "../text/style-write.js";
7
12
  //#region src/drawing/shapes-write.ts
13
+ function insetProperties(shape, isPicture) {
14
+ const defaultLeftRight = isPicture ? 0 : DEFAULT_INSET_LEFT_RIGHT_PT;
15
+ const defaultTopBottom = isPicture ? 0 : DEFAULT_INSET_TOP_BOTTOM_PT;
16
+ const entries = [];
17
+ if (shape.insetLeftPt !== defaultLeftRight) entries.push({
18
+ opid: 129,
19
+ op: pointsToEmu(shape.insetLeftPt)
20
+ });
21
+ if (shape.insetTopPt !== defaultTopBottom) entries.push({
22
+ opid: 130,
23
+ op: pointsToEmu(shape.insetTopPt)
24
+ });
25
+ if (shape.insetRightPt !== defaultLeftRight) entries.push({
26
+ opid: 131,
27
+ op: pointsToEmu(shape.insetRightPt)
28
+ });
29
+ if (shape.insetBottomPt !== defaultTopBottom) entries.push({
30
+ opid: 132,
31
+ op: pointsToEmu(shape.insetBottomPt)
32
+ });
33
+ return entries;
34
+ }
35
+ const FSP_CHILD = 2;
8
36
  const PATRIARCH_SPID = 1;
9
37
  const FIRST_CONTENT_SPID = 2;
10
38
  function writeFsp(spid, flags) {
@@ -20,9 +48,23 @@ function writeClientAnchor(xPt, yPt, widthPt, heightPt) {
20
48
  function writeTextCharsAtom(text) {
21
49
  return writeAtom(RT_TextCharsAtom, utf16le(text));
22
50
  }
23
- function writeClientTextbox(shape, fontIndexOf) {
24
- if (!shape.blocks.some((block) => block.kind === "paragraph")) return;
25
- const { text, style } = buildTextBody(shape.blocks, fontIndexOf);
51
+ function writeShapeProperties(shape, pib) {
52
+ const entries = [];
53
+ if (shape.rotationDeg !== void 0) entries.push({
54
+ opid: 4,
55
+ op: degreesToFixedPoint(shape.rotationDeg)
56
+ });
57
+ if (pib !== void 0) entries.push({
58
+ opid: 260,
59
+ op: pib,
60
+ fBid: true
61
+ });
62
+ entries.push(...insetProperties(shape, pib !== void 0));
63
+ return entries.length === 0 ? void 0 : writeShapePropertyTable(OfficeArtFOPT, entries);
64
+ }
65
+ function writeClientTextbox(textBlocks, fontIndexOf) {
66
+ if (textBlocks.length === 0) return;
67
+ const { text, style } = buildTextBody(textBlocks, fontIndexOf);
26
68
  const totalParagraphCount = style.paragraphRuns.reduce((sum, run) => sum + run.count, 0);
27
69
  if (totalParagraphCount !== characterCountOf(text)) throw new Error(`internal error: built ${totalParagraphCount} characters of paragraph runs for a ${characterCountOf(text)}-character text body`);
28
70
  return writeContainer(OfficeArtClientTextbox, [
@@ -31,9 +73,12 @@ function writeClientTextbox(shape, fontIndexOf) {
31
73
  writeStyleTextPropAtom(style)
32
74
  ]);
33
75
  }
34
- function writeShape(spid, shape, fontIndexOf, clientData) {
35
- const clientTextbox = writeClientTextbox(shape, fontIndexOf);
36
- const children = [writeFsp(spid, 0), writeClientAnchor(shape.frame.xPt, shape.frame.yPt, shape.frame.widthPt, shape.frame.heightPt)];
76
+ function writeShape(spid, shape, pib, textBlocks, fontIndexOf, clientData) {
77
+ const properties = writeShapeProperties(shape, pib);
78
+ const clientTextbox = writeClientTextbox(textBlocks, fontIndexOf);
79
+ const children = [writeFsp(spid, 0)];
80
+ if (properties !== void 0) children.push(properties);
81
+ children.push(writeClientAnchor(shape.frame.xPt, shape.frame.yPt, shape.frame.widthPt, shape.frame.heightPt));
37
82
  if (clientData !== void 0) children.push(clientData);
38
83
  if (clientTextbox !== void 0) children.push(clientTextbox);
39
84
  return writeContainer(OfficeArtSpContainer, children);
@@ -41,18 +86,191 @@ function writeShape(spid, shape, fontIndexOf, clientData) {
41
86
  function writePatriarch() {
42
87
  return writeContainer(OfficeArtSpContainer, [writeAtom(OfficeArtFSPGR, /* @__PURE__ */ new Uint8Array(16), { recVer: 1 }), writeFsp(PATRIARCH_SPID, 5)]);
43
88
  }
44
- function writeDrawing(shapes, fontIndexOf) {
45
- const shapeContainers = shapes.map((entry, index) => writeShape(FIRST_CONTENT_SPID + index, entry.shape, fontIndexOf, entry.clientData));
46
- return writeContainer(RT_Drawing, [writeContainer(OfficeArtDgContainer, [writeContainer(OfficeArtSpgrContainer, [writePatriarch(), ...shapeContainers])])]);
89
+ function reportDrop(context, diagnostic) {
90
+ context.sink(diagnostic);
91
+ if (context.strict) throw new PptUnsupportedContentError(diagnostic.message);
92
+ }
93
+ function planShapeBlocks(blocks, context, hasOleClientData) {
94
+ const textBlocks = [];
95
+ let pib;
96
+ let table;
97
+ const drop = (block, reason) => {
98
+ reportDrop(context, {
99
+ code: PptDiagnosticCodes.BLOCK_DROPPED,
100
+ severity: "warning",
101
+ message: `${context.location}: ${reason}`
102
+ });
103
+ };
104
+ for (const block of blocks) {
105
+ if (block.kind === "embeddedObject" && hasOleClientData) continue;
106
+ if (block.kind === "paragraph") {
107
+ textBlocks.push(block);
108
+ continue;
109
+ }
110
+ if (block.kind === "image") {
111
+ if (!isBlipFormat(block.format)) {
112
+ reportDrop(context, {
113
+ code: PptDiagnosticCodes.IMAGE_DROPPED,
114
+ severity: "warning",
115
+ message: `${context.location}: an image block in format '${block.format}' is dropped; MSOBLIPTYPE gives this writer a blip record for PNG and JPEG only`
116
+ });
117
+ continue;
118
+ }
119
+ if (pib !== void 0) {
120
+ reportDrop(context, {
121
+ code: PptDiagnosticCodes.IMAGE_DROPPED,
122
+ severity: "warning",
123
+ message: `${context.location}: a second image block is dropped; a shape carries exactly one blip-store reference, and an earlier image already consumed it`
124
+ });
125
+ continue;
126
+ }
127
+ pib = context.blipIndexOf(block);
128
+ continue;
129
+ }
130
+ if (block.kind === "table") {
131
+ if (table !== void 0) {
132
+ drop(block, "a second 'table' block is dropped; a shape becomes one table group, and an earlier table already did");
133
+ continue;
134
+ }
135
+ table = block;
136
+ continue;
137
+ }
138
+ drop(block, `a '${block.kind}' block is dropped; this writer produces no [MS-PPT] spelling for it`);
139
+ }
140
+ if (table !== void 0) {
141
+ for (const block of textBlocks) drop(block, "a 'paragraph' block is dropped; a shape carrying a table becomes a table group, which holds its text in cells rather than a text body of its own");
142
+ if (pib !== void 0) reportDrop(context, {
143
+ code: PptDiagnosticCodes.IMAGE_DROPPED,
144
+ severity: "warning",
145
+ message: `${context.location}: an image block is dropped; a shape carrying a table becomes a table group, which has no blip reference of its own`
146
+ });
147
+ return {
148
+ pib: void 0,
149
+ textBlocks: [],
150
+ table
151
+ };
152
+ }
153
+ return {
154
+ pib,
155
+ textBlocks,
156
+ table
157
+ };
158
+ }
159
+ function tableRowHeights(table, frameHeightMasterUnits) {
160
+ const stated = table.rows.map((row) => row.heightPt === void 0 ? void 0 : pointsToMasterUnits(row.heightPt));
161
+ const unstatedCount = stated.filter((height) => height === void 0).length;
162
+ if (unstatedCount === 0) return stated.map((height) => {
163
+ if (height === void 0) throw new Error("internal error: a stated row height became unstated in the same pass");
164
+ return height;
165
+ });
166
+ const remaining = frameHeightMasterUnits - stated.reduce((sum, height) => sum + (height ?? 0), 0);
167
+ const shared = Math.max(1, Math.round(remaining / unstatedCount));
168
+ return stated.map((height) => height ?? shared);
169
+ }
170
+ function writeTableGroup(spid, shape, table, context) {
171
+ const { frame } = shape;
172
+ const rowHeights = tableRowHeights(table, pointsToMasterUnits(frame.heightPt));
173
+ const declaredWidths = table.columnWidthsPt.map(pointsToMasterUnits);
174
+ const cellCount = Math.max(1, ...table.rows.map((row) => row.cells.length), declaredWidths.length);
175
+ const lastDeclared = declaredWidths.at(-1);
176
+ const equalShare = Math.max(1, Math.round(pointsToMasterUnits(frame.widthPt) / cellCount));
177
+ const columnWidthsMasterUnits = Array.from({ length: cellCount }, (_, index) => declaredWidths[index] ?? lastDeclared ?? equalShare);
178
+ const columnBoundaries = [];
179
+ let columnEdge = pointsToMasterUnits(frame.xPt);
180
+ for (const width of columnWidthsMasterUnits) {
181
+ columnBoundaries.push(columnEdge);
182
+ columnEdge += width;
183
+ }
184
+ columnBoundaries.push(columnEdge);
185
+ const rowBoundaries = [];
186
+ let rowEdge = pointsToMasterUnits(frame.yPt);
187
+ for (const height of rowHeights) {
188
+ rowBoundaries.push(rowEdge);
189
+ rowEdge += height;
190
+ }
191
+ rowBoundaries.push(rowEdge);
192
+ const rowHeightsPayload = writeIMsoArray(rowHeights, 4);
193
+ const tableLeft = pointsToMasterUnits(frame.xPt);
194
+ const tableTop = pointsToMasterUnits(frame.yPt);
195
+ const tableRight = pointsToMasterUnits(frame.xPt + frame.widthPt);
196
+ const tableBottom = pointsToMasterUnits(frame.yPt + frame.heightPt);
197
+ const groupShape = writeContainer(OfficeArtSpContainer, [
198
+ writeAtom(OfficeArtFSPGR, concatBytes(i32le(tableLeft), i32le(tableTop), i32le(tableRight), i32le(tableBottom)), { recVer: 1 }),
199
+ writeFsp(spid, 513),
200
+ ...shape.rotationDeg === void 0 ? [] : [writeShapePropertyTable(OfficeArtFOPT, [{
201
+ opid: 4,
202
+ op: degreesToFixedPoint(shape.rotationDeg)
203
+ }])],
204
+ writeShapePropertyTable(OfficeArtTertiaryFOPT, [{
205
+ opid: 927,
206
+ op: 1
207
+ }, {
208
+ opid: 928,
209
+ op: rowHeightsPayload.length,
210
+ fBid: true,
211
+ complex: rowHeightsPayload
212
+ }]),
213
+ writeClientAnchor(frame.xPt, frame.yPt, frame.widthPt, frame.heightPt)
214
+ ]);
215
+ let cellSpid = spid + 1;
216
+ const cellShapes = table.rows.flatMap((row, rowIndex) => row.cells.map((cell, columnIndex) => {
217
+ const cellLeft = columnBoundaries[columnIndex];
218
+ const cellRight = columnBoundaries[columnIndex + 1];
219
+ const cellTop = rowBoundaries[rowIndex];
220
+ const cellBottom = rowBoundaries[rowIndex + 1];
221
+ if (cellLeft === void 0 || cellRight === void 0 || cellTop === void 0 || cellBottom === void 0) throw new Error("internal error: a table cell sits outside the grid boundaries derived from its own table");
222
+ if (cell.colSpan !== void 0 && cell.colSpan > 1) context.sink({
223
+ code: PptDiagnosticCodes.TABLE_SPAN_DROPPED,
224
+ severity: "warning",
225
+ message: `${context.location}: a table cell's colSpan ${String(cell.colSpan)} is dropped; a PowerPoint 97-2003 table is a strict grid of shapes with no merge records, so the cell is written one column wide`
226
+ });
227
+ if (cell.rowSpan !== void 0 && cell.rowSpan > 1) context.sink({
228
+ code: PptDiagnosticCodes.TABLE_SPAN_DROPPED,
229
+ severity: "warning",
230
+ message: `${context.location}: a table cell's rowSpan ${String(cell.rowSpan)} is dropped; a PowerPoint 97-2003 table is a strict grid of shapes with no merge records, so the cell is written one row tall`
231
+ });
232
+ const paragraphs = cell.blocks.filter((block) => block.kind === "paragraph");
233
+ for (const block of cell.blocks) if (block.kind !== "paragraph") reportDrop(context, {
234
+ code: PptDiagnosticCodes.BLOCK_DROPPED,
235
+ severity: "warning",
236
+ message: `${context.location}: a '${block.kind}' block inside a table cell is dropped; a table cell in this format is a plain text-box shape with no property table or object reference of its own`
237
+ });
238
+ const textbox = writeClientTextbox(paragraphs, context.fontIndexOf);
239
+ const children = [writeFsp(cellSpid, FSP_CHILD), writeAtom(OfficeArtChildAnchor, concatBytes(i32le(cellLeft), i32le(cellTop), i32le(cellRight), i32le(cellBottom)))];
240
+ cellSpid += 1;
241
+ if (textbox !== void 0) children.push(textbox);
242
+ return writeContainer(OfficeArtSpContainer, children);
243
+ }));
244
+ return {
245
+ bytes: writeContainer(OfficeArtSpgrContainer, [groupShape, ...cellShapes]),
246
+ shapeCount: 1 + table.rows.reduce((sum, row) => sum + row.cells.length, 0)
247
+ };
47
248
  }
48
- function writeSlideDrawing(shapes, fontIndexOf) {
49
- return writeDrawing(shapes.map((shape) => ({
50
- shape,
51
- clientData: void 0
52
- })), fontIndexOf);
249
+ function writeDrawing(shapes, context) {
250
+ let nextSpid = FIRST_CONTENT_SPID;
251
+ let shapeCount = 1;
252
+ const shapeContainers = [];
253
+ for (const entry of shapes) {
254
+ const plan = planShapeBlocks(entry.shape.blocks, context, entry.clientData !== void 0);
255
+ if (plan.table !== void 0) {
256
+ const group = writeTableGroup(nextSpid, entry.shape, plan.table, context);
257
+ nextSpid += group.shapeCount;
258
+ shapeCount += group.shapeCount;
259
+ shapeContainers.push(group.bytes);
260
+ continue;
261
+ }
262
+ shapeContainers.push(writeShape(nextSpid, entry.shape, plan.pib, plan.textBlocks, context.fontIndexOf, entry.clientData));
263
+ nextSpid += 1;
264
+ shapeCount += 1;
265
+ }
266
+ return {
267
+ bytes: writeContainer(RT_Drawing, [writeContainer(OfficeArtDgContainer, [writeContainer(OfficeArtSpgrContainer, [writePatriarch(), ...shapeContainers])])]),
268
+ shapeCount,
269
+ maxSpid: Math.max(PATRIARCH_SPID, nextSpid - 1)
270
+ };
53
271
  }
54
- function writeDrawingWithClientData(shapes, fontIndexOf) {
55
- return writeDrawing(shapes, fontIndexOf);
272
+ function writeSlideDrawing(shapes, context) {
273
+ return writeDrawing(shapes, context);
56
274
  }
57
275
  //#endregion
58
- export { writeDrawingWithClientData, writeSlideDrawing };
276
+ export { writeSlideDrawing };
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_errors = require("../errors.cjs");
3
3
  const require_record_tree = require("../record/tree.cjs");
4
4
  const require_record_types = require("../record/types.cjs");
5
+ const require_drawing_properties = require("./properties.cjs");
5
6
  //#region src/drawing/shapes.ts
6
7
  const FSP_GROUP = 1;
7
8
  const FSP_PATRIARCH = 4;
@@ -44,7 +45,7 @@ function readClientAnchor(record) {
44
45
  if (recLen === 16) return readRectFields(record, 4, "top-left");
45
46
  throw new require_errors.PptFormatError(`OfficeArtClientAnchor declares recLen 0x${recLen.toString(16)}, neither the 0x8 of a SmallRectStruct nor the 0x10 of a RectStruct`);
46
47
  }
47
- function readShapeProperties(shape) {
48
+ function readShapeIdentity(shape) {
48
49
  const fsp = require_record_tree.findChild(require_record_tree.childRecords(shape), require_record_types.OfficeArtFSP);
49
50
  if (fsp === void 0 || fsp.data.length < 8) throw new require_errors.PptFormatError(`OfficeArtSpContainer at offset ${shape.offset} has no readable OfficeArtFSP, so the shape has neither an identity nor its flags`);
50
51
  const view = new DataView(fsp.data.buffer, fsp.data.byteOffset, 8);
@@ -60,8 +61,18 @@ function resolveAnchor(shape, transform) {
60
61
  const child = require_record_tree.findChild(children, require_record_types.OfficeArtChildAnchor);
61
62
  if (child !== void 0) return applyTransform(transform, readRectFields(child, 4, "left-top"));
62
63
  }
64
+ function rotationDegOf(properties) {
65
+ const rotation = properties.get(4);
66
+ if (rotation === void 0) return;
67
+ const degrees = require_drawing_properties.fixedPointToDegrees(rotation.value);
68
+ return degrees === 0 ? void 0 : degrees;
69
+ }
70
+ function isTableGroup(properties) {
71
+ const tableProperties = properties.get(927);
72
+ return tableProperties !== void 0 && (tableProperties.value & 1) !== 0;
73
+ }
63
74
  function groupTransform(groupShape, parent) {
64
- const { spid, flags } = readShapeProperties(groupShape);
75
+ const { spid, flags } = readShapeIdentity(groupShape);
65
76
  if ((flags & FSP_PATRIARCH) !== 0) return parent;
66
77
  const children = require_record_tree.childRecords(groupShape);
67
78
  const fspgr = require_record_tree.findChild(children, require_record_types.OfficeArtFSPGR);
@@ -81,17 +92,36 @@ function groupTransform(groupShape, parent) {
81
92
  };
82
93
  }
83
94
  function collectShape(shape, transform, into) {
84
- const { spid, flags } = readShapeProperties(shape);
95
+ const { spid, flags } = readShapeIdentity(shape);
85
96
  if ((flags & FSP_DELETED) !== 0 || (flags & FSP_GROUP) !== 0) return;
97
+ const children = require_record_tree.childRecords(shape);
98
+ const properties = require_drawing_properties.readShapeProperties(shape);
86
99
  into.push({
87
100
  spid,
88
101
  anchor: resolveAnchor(shape, transform),
89
- clientTextbox: require_record_tree.findChild(require_record_tree.childRecords(shape), require_record_types.OfficeArtClientTextbox)
102
+ rotationDeg: rotationDegOf(properties),
103
+ clientTextbox: require_record_tree.findChild(children, require_record_types.OfficeArtClientTextbox),
104
+ clientData: require_record_tree.findChild(children, require_record_types.OfficeArtClientData),
105
+ properties
90
106
  });
91
107
  }
92
108
  function collectGroup(group, parent, into) {
93
109
  const [groupShape, ...rest] = require_record_tree.childRecords(group);
94
110
  if (groupShape === void 0) return;
111
+ const groupProperties = require_drawing_properties.readShapeProperties(groupShape);
112
+ if (isTableGroup(groupProperties)) {
113
+ const anchor = resolveAnchor(groupShape, parent);
114
+ if (anchor === void 0) throw new require_errors.PptFormatError(`table group shape ${readShapeIdentity(groupShape).spid} carries no anchor, so the table cannot be placed on the slide`);
115
+ const tableTransform = groupTransform(groupShape, parent);
116
+ const cells = [];
117
+ for (const child of rest) if (child.header.recType === 61444) collectShape(child, tableTransform, cells);
118
+ into.push({
119
+ anchor,
120
+ rotationDeg: rotationDegOf(groupProperties),
121
+ cells
122
+ });
123
+ return;
124
+ }
95
125
  const transform = groupTransform(groupShape, parent);
96
126
  for (const child of rest) if (child.header.recType === 61443) collectGroup(child, transform, into);
97
127
  else if (child.header.recType === 61444) collectShape(child, transform, into);
@@ -1,4 +1,5 @@
1
1
  import { t as PptRecord } from "../tree-Du_LXAF0.cjs";
2
+ import { ShapeProperty } from "./properties.cjs";
2
3
  //#region src/drawing/shapes.d.ts
3
4
  interface ShapeRect {
4
5
  readonly left: number;
@@ -9,8 +10,16 @@ interface ShapeRect {
9
10
  interface PptShape {
10
11
  readonly spid: number;
11
12
  readonly anchor: ShapeRect | undefined;
13
+ readonly rotationDeg: number | undefined;
12
14
  readonly clientTextbox: PptRecord | undefined;
15
+ readonly clientData: PptRecord | undefined;
16
+ readonly properties: ReadonlyMap<number, ShapeProperty>;
13
17
  }
14
- declare function readDrawingShapes(drawing: PptRecord): PptShape[];
18
+ interface PptTable {
19
+ readonly anchor: ShapeRect;
20
+ readonly rotationDeg: number | undefined;
21
+ readonly cells: readonly PptShape[];
22
+ }
23
+ declare function readDrawingShapes(drawing: PptRecord): readonly (PptShape | PptTable)[];
15
24
  //#endregion
16
- export { PptShape, ShapeRect, readDrawingShapes };
25
+ export { PptShape, PptTable, ShapeRect, readDrawingShapes };
@@ -1,4 +1,5 @@
1
1
  import { t as PptRecord } from "../tree-PMcPNgd-.js";
2
+ import { ShapeProperty } from "./properties.js";
2
3
  //#region src/drawing/shapes.d.ts
3
4
  interface ShapeRect {
4
5
  readonly left: number;
@@ -9,8 +10,16 @@ interface ShapeRect {
9
10
  interface PptShape {
10
11
  readonly spid: number;
11
12
  readonly anchor: ShapeRect | undefined;
13
+ readonly rotationDeg: number | undefined;
12
14
  readonly clientTextbox: PptRecord | undefined;
15
+ readonly clientData: PptRecord | undefined;
16
+ readonly properties: ReadonlyMap<number, ShapeProperty>;
13
17
  }
14
- declare function readDrawingShapes(drawing: PptRecord): PptShape[];
18
+ interface PptTable {
19
+ readonly anchor: ShapeRect;
20
+ readonly rotationDeg: number | undefined;
21
+ readonly cells: readonly PptShape[];
22
+ }
23
+ declare function readDrawingShapes(drawing: PptRecord): readonly (PptShape | PptTable)[];
15
24
  //#endregion
16
- export { PptShape, ShapeRect, readDrawingShapes };
25
+ export { PptShape, PptTable, ShapeRect, readDrawingShapes };
@@ -1,6 +1,7 @@
1
1
  import { PptFormatError } from "../errors.js";
2
2
  import { childRecords, findChild } from "../record/tree.js";
3
- import { OfficeArtChildAnchor, OfficeArtClientAnchor, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtFSP, OfficeArtFSPGR, RT_Drawing } from "../record/types.js";
3
+ import { OfficeArtChildAnchor, OfficeArtClientAnchor, OfficeArtClientData, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtFSP, OfficeArtFSPGR, RT_Drawing } from "../record/types.js";
4
+ import { fixedPointToDegrees, readShapeProperties } from "./properties.js";
4
5
  //#region src/drawing/shapes.ts
5
6
  const FSP_GROUP = 1;
6
7
  const FSP_PATRIARCH = 4;
@@ -43,7 +44,7 @@ function readClientAnchor(record) {
43
44
  if (recLen === 16) return readRectFields(record, 4, "top-left");
44
45
  throw new PptFormatError(`OfficeArtClientAnchor declares recLen 0x${recLen.toString(16)}, neither the 0x8 of a SmallRectStruct nor the 0x10 of a RectStruct`);
45
46
  }
46
- function readShapeProperties(shape) {
47
+ function readShapeIdentity(shape) {
47
48
  const fsp = findChild(childRecords(shape), OfficeArtFSP);
48
49
  if (fsp === void 0 || fsp.data.length < 8) throw new PptFormatError(`OfficeArtSpContainer at offset ${shape.offset} has no readable OfficeArtFSP, so the shape has neither an identity nor its flags`);
49
50
  const view = new DataView(fsp.data.buffer, fsp.data.byteOffset, 8);
@@ -59,8 +60,18 @@ function resolveAnchor(shape, transform) {
59
60
  const child = findChild(children, OfficeArtChildAnchor);
60
61
  if (child !== void 0) return applyTransform(transform, readRectFields(child, 4, "left-top"));
61
62
  }
63
+ function rotationDegOf(properties) {
64
+ const rotation = properties.get(4);
65
+ if (rotation === void 0) return;
66
+ const degrees = fixedPointToDegrees(rotation.value);
67
+ return degrees === 0 ? void 0 : degrees;
68
+ }
69
+ function isTableGroup(properties) {
70
+ const tableProperties = properties.get(927);
71
+ return tableProperties !== void 0 && (tableProperties.value & 1) !== 0;
72
+ }
62
73
  function groupTransform(groupShape, parent) {
63
- const { spid, flags } = readShapeProperties(groupShape);
74
+ const { spid, flags } = readShapeIdentity(groupShape);
64
75
  if ((flags & FSP_PATRIARCH) !== 0) return parent;
65
76
  const children = childRecords(groupShape);
66
77
  const fspgr = findChild(children, OfficeArtFSPGR);
@@ -80,17 +91,36 @@ function groupTransform(groupShape, parent) {
80
91
  };
81
92
  }
82
93
  function collectShape(shape, transform, into) {
83
- const { spid, flags } = readShapeProperties(shape);
94
+ const { spid, flags } = readShapeIdentity(shape);
84
95
  if ((flags & FSP_DELETED) !== 0 || (flags & FSP_GROUP) !== 0) return;
96
+ const children = childRecords(shape);
97
+ const properties = readShapeProperties(shape);
85
98
  into.push({
86
99
  spid,
87
100
  anchor: resolveAnchor(shape, transform),
88
- clientTextbox: findChild(childRecords(shape), OfficeArtClientTextbox)
101
+ rotationDeg: rotationDegOf(properties),
102
+ clientTextbox: findChild(children, OfficeArtClientTextbox),
103
+ clientData: findChild(children, OfficeArtClientData),
104
+ properties
89
105
  });
90
106
  }
91
107
  function collectGroup(group, parent, into) {
92
108
  const [groupShape, ...rest] = childRecords(group);
93
109
  if (groupShape === void 0) return;
110
+ const groupProperties = readShapeProperties(groupShape);
111
+ if (isTableGroup(groupProperties)) {
112
+ const anchor = resolveAnchor(groupShape, parent);
113
+ if (anchor === void 0) throw new PptFormatError(`table group shape ${readShapeIdentity(groupShape).spid} carries no anchor, so the table cannot be placed on the slide`);
114
+ const tableTransform = groupTransform(groupShape, parent);
115
+ const cells = [];
116
+ for (const child of rest) if (child.header.recType === 61444) collectShape(child, tableTransform, cells);
117
+ into.push({
118
+ anchor,
119
+ rotationDeg: rotationDegOf(groupProperties),
120
+ cells
121
+ });
122
+ return;
123
+ }
94
124
  const transform = groupTransform(groupShape, parent);
95
125
  for (const child of rest) if (child.header.recType === 61443) collectGroup(child, transform, into);
96
126
  else if (child.header.recType === 61444) collectShape(child, transform, into);
package/dist/index.cjs CHANGED
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_base64 = require("./base64.cjs");
2
3
  const require_errors = require("./errors.cjs");
3
4
  const require_record_header = require("./record/header.cjs");
4
5
  const require_record_tree = require("./record/tree.cjs");
@@ -8,14 +9,15 @@ const require_text_atoms = require("./text/atoms.cjs");
8
9
  const require_units = require("./units.cjs");
9
10
  const require_content_write = require("./content-write.cjs");
10
11
  const require_content = require("./content.cjs");
12
+ const require_diagnostics = require("./diagnostics.cjs");
11
13
  const require_record_write = require("./record/write.cjs");
12
14
  const require_document_color_scheme_write = require("./document/color-scheme-write.cjs");
13
15
  const require_document_document_atom = require("./document/document-atom.cjs");
14
16
  const require_document_document_atom_write = require("./document/document-atom-write.cjs");
15
17
  const require_document_fonts = require("./document/fonts.cjs");
16
18
  const require_document_fonts_write = require("./document/fonts-write.cjs");
17
- const require_text_style_write = require("./text/style-write.cjs");
18
- const require_drawing_shapes_write = require("./drawing/shapes-write.cjs");
19
+ const require_drawing_blips = require("./drawing/blips.cjs");
20
+ const require_drawing_properties = require("./drawing/properties.cjs");
19
21
  const require_document_notes_list = require("./document/notes-list.cjs");
20
22
  const require_drawing_shapes = require("./drawing/shapes.cjs");
21
23
  const require_document_notes = require("./document/notes.cjs");
@@ -23,6 +25,8 @@ const require_document_slide_list = require("./document/slide-list.cjs");
23
25
  const require_stream_current_user = require("./stream/current-user.cjs");
24
26
  const require_stream_persist = require("./stream/persist.cjs");
25
27
  const require_read = require("./read.cjs");
28
+ const require_text_style_write = require("./text/style-write.cjs");
29
+ const require_drawing_shapes_write = require("./drawing/shapes-write.cjs");
26
30
  const require_document_master_write = require("./document/master-write.cjs");
27
31
  const require_document_notes_list_write = require("./document/notes-list-write.cjs");
28
32
  const require_document_notes_write = require("./document/notes-write.cjs");
@@ -64,20 +68,30 @@ exports.CURRENT_USER_HEADER_TOKEN_PLAIN = require_stream_current_user.CURRENT_US
64
68
  exports.CURRENT_USER_STREAM = require_read.CURRENT_USER_STREAM;
65
69
  exports.DEFAULT_INSET_LEFT_RIGHT_PT = require_read.DEFAULT_INSET_LEFT_RIGHT_PT;
66
70
  exports.DEFAULT_INSET_TOP_BOTTOM_PT = require_read.DEFAULT_INSET_TOP_BOTTOM_PT;
71
+ exports.EMU_PER_POINT = require_units.EMU_PER_POINT;
67
72
  exports.LINE_BREAK = require_text_atoms.LINE_BREAK;
68
73
  exports.MASTER_SLIDE_ID = require_document_master_write.MASTER_SLIDE_ID;
69
74
  exports.MASTER_UNITS_PER_POINT = require_units.MASTER_UNITS_PER_POINT;
75
+ exports.NOOP_PPT_DIAGNOSTIC_SINK = require_diagnostics.NOOP_PPT_DIAGNOSTIC_SINK;
70
76
  exports.NOTES_MASTER_SLIDE_ID_REF = require_document_notes.NOTES_MASTER_SLIDE_ID_REF;
77
+ exports.OfficeArtBStoreContainer = require_record_types.OfficeArtBStoreContainer;
78
+ exports.OfficeArtBlipJPEG = require_record_types.OfficeArtBlipJPEG;
79
+ exports.OfficeArtBlipPNG = require_record_types.OfficeArtBlipPNG;
71
80
  exports.OfficeArtChildAnchor = require_record_types.OfficeArtChildAnchor;
72
81
  exports.OfficeArtClientAnchor = require_record_types.OfficeArtClientAnchor;
73
82
  exports.OfficeArtClientData = require_record_types.OfficeArtClientData;
74
83
  exports.OfficeArtClientTextbox = require_record_types.OfficeArtClientTextbox;
75
84
  exports.OfficeArtDgContainer = require_record_types.OfficeArtDgContainer;
85
+ exports.OfficeArtDggContainer = require_record_types.OfficeArtDggContainer;
86
+ exports.OfficeArtFBSE = require_record_types.OfficeArtFBSE;
87
+ exports.OfficeArtFDGGBlock = require_record_types.OfficeArtFDGGBlock;
76
88
  exports.OfficeArtFOPT = require_record_types.OfficeArtFOPT;
77
89
  exports.OfficeArtFSP = require_record_types.OfficeArtFSP;
78
90
  exports.OfficeArtFSPGR = require_record_types.OfficeArtFSPGR;
91
+ exports.OfficeArtSecondaryFOPT = require_record_types.OfficeArtSecondaryFOPT;
79
92
  exports.OfficeArtSpContainer = require_record_types.OfficeArtSpContainer;
80
93
  exports.OfficeArtSpgrContainer = require_record_types.OfficeArtSpgrContainer;
94
+ exports.OfficeArtTertiaryFOPT = require_record_types.OfficeArtTertiaryFOPT;
81
95
  exports.PARAGRAPH_SEPARATOR = require_text_atoms.PARAGRAPH_SEPARATOR;
82
96
  exports.PF_ALIGN = require_text_style.PF_ALIGN;
83
97
  exports.PF_BULLET_CHAR = require_text_style.PF_BULLET_CHAR;
@@ -100,8 +114,18 @@ exports.PF_SPACE_BEFORE = require_text_style.PF_SPACE_BEFORE;
100
114
  exports.PF_TAB_STOPS = require_text_style.PF_TAB_STOPS;
101
115
  exports.PF_TEXT_DIRECTION = require_text_style.PF_TEXT_DIRECTION;
102
116
  exports.PF_WORD_WRAP = require_text_style.PF_WORD_WRAP;
117
+ exports.PICTURES_STREAM = require_read.PICTURES_STREAM;
103
118
  exports.POINTS_PER_INCH = require_units.POINTS_PER_INCH;
104
119
  exports.POWERPOINT_DOCUMENT_STREAM = require_read.POWERPOINT_DOCUMENT_STREAM;
120
+ exports.PROPERTY_DX_TEXT_LEFT = require_drawing_properties.PROPERTY_DX_TEXT_LEFT;
121
+ exports.PROPERTY_DX_TEXT_RIGHT = require_drawing_properties.PROPERTY_DX_TEXT_RIGHT;
122
+ exports.PROPERTY_DY_TEXT_BOTTOM = require_drawing_properties.PROPERTY_DY_TEXT_BOTTOM;
123
+ exports.PROPERTY_DY_TEXT_TOP = require_drawing_properties.PROPERTY_DY_TEXT_TOP;
124
+ exports.PROPERTY_PIB = require_drawing_properties.PROPERTY_PIB;
125
+ exports.PROPERTY_ROTATION = require_drawing_properties.PROPERTY_ROTATION;
126
+ exports.PROPERTY_TABLE_PROPERTIES = require_drawing_properties.PROPERTY_TABLE_PROPERTIES;
127
+ exports.PROPERTY_TABLE_ROW_PROPERTIES = require_drawing_properties.PROPERTY_TABLE_ROW_PROPERTIES;
128
+ exports.PptDiagnosticCodes = require_diagnostics.PptDiagnosticCodes;
105
129
  exports.PptEncryptedError = require_errors.PptEncryptedError;
106
130
  exports.PptFormatError = require_errors.PptFormatError;
107
131
  exports.PptUnsupportedContentError = require_errors.PptUnsupportedContentError;
@@ -116,6 +140,12 @@ exports.RT_Drawing = require_record_types.RT_Drawing;
116
140
  exports.RT_DrawingGroup = require_record_types.RT_DrawingGroup;
117
141
  exports.RT_Environment = require_record_types.RT_Environment;
118
142
  exports.RT_ExternalObjectList = require_record_types.RT_ExternalObjectList;
143
+ exports.RT_ExternalObjectListAtom = require_record_types.RT_ExternalObjectListAtom;
144
+ exports.RT_ExternalObjectRefAtom = require_record_types.RT_ExternalObjectRefAtom;
145
+ exports.RT_ExternalOleEmbed = require_record_types.RT_ExternalOleEmbed;
146
+ exports.RT_ExternalOleEmbedAtom = require_record_types.RT_ExternalOleEmbedAtom;
147
+ exports.RT_ExternalOleObjectAtom = require_record_types.RT_ExternalOleObjectAtom;
148
+ exports.RT_ExternalOleObjectStg = require_record_types.RT_ExternalOleObjectStg;
119
149
  exports.RT_FontCollection = require_record_types.RT_FontCollection;
120
150
  exports.RT_FontEntityAtom = require_record_types.RT_FontEntityAtom;
121
151
  exports.RT_List = require_record_types.RT_List;
@@ -148,6 +178,7 @@ exports.STYLE_ITALIC = require_text_style.STYLE_ITALIC;
148
178
  exports.STYLE_SHADOW = require_text_style.STYLE_SHADOW;
149
179
  exports.STYLE_UNDERLINE = require_text_style.STYLE_UNDERLINE;
150
180
  exports.SUMMARY_INFORMATION_STREAM = require_read.SUMMARY_INFORMATION_STREAM;
181
+ exports.TABLE_FLAG_IS_TABLE = require_drawing_properties.TABLE_FLAG_IS_TABLE;
151
182
  exports.TEXT_TYPE_BODY = require_text_atoms.TEXT_TYPE_BODY;
152
183
  exports.TEXT_TYPE_CENTER_BODY = require_text_atoms.TEXT_TYPE_CENTER_BODY;
153
184
  exports.TEXT_TYPE_CENTER_TITLE = require_text_atoms.TEXT_TYPE_CENTER_TITLE;
@@ -157,26 +188,37 @@ exports.TEXT_TYPE_OTHER = require_text_atoms.TEXT_TYPE_OTHER;
157
188
  exports.TEXT_TYPE_QUARTER_BODY = require_text_atoms.TEXT_TYPE_QUARTER_BODY;
158
189
  exports.TEXT_TYPE_TITLE = require_text_atoms.TEXT_TYPE_TITLE;
159
190
  exports.asciiBytes = require_record_write.asciiBytes;
191
+ exports.base64ToBytes = require_base64.base64ToBytes;
192
+ exports.blipForPib = require_drawing_blips.blipForPib;
160
193
  exports.buildParagraphs = require_content.buildParagraphs;
161
194
  exports.buildPersistDirectory = require_stream_persist.buildPersistDirectory;
162
195
  exports.buildTextBody = require_content_write.buildTextBody;
196
+ exports.bytesToBase64 = require_base64.bytesToBase64;
163
197
  exports.characterCountOf = require_text_atoms.characterCountOf;
164
198
  exports.childRecords = require_record_tree.childRecords;
165
199
  exports.collectFontFamilies = require_content_write.collectFontFamilies;
166
200
  exports.concatBytes = require_record_write.concatBytes;
201
+ exports.decodeUtf16Le = require_stream_current_user.decodeUtf16Le;
202
+ exports.degreesToFixedPoint = require_drawing_properties.degreesToFixedPoint;
203
+ exports.emuToPoints = require_units.emuToPoints;
167
204
  exports.findChild = require_record_tree.findChild;
168
205
  exports.findChildren = require_record_tree.findChildren;
169
206
  exports.findDescendants = require_record_tree.findDescendants;
207
+ exports.fixedPointToDegrees = require_drawing_properties.fixedPointToDegrees;
170
208
  exports.i16le = require_record_write.i16le;
171
209
  exports.i32le = require_record_write.i32le;
210
+ exports.isBlipFormat = require_drawing_blips.isBlipFormat;
172
211
  exports.isContainerRecord = require_record_header.isContainerRecord;
173
212
  exports.layoutMetadataToSummaryInformation = require_metadata.layoutMetadataToSummaryInformation;
174
213
  exports.masterUnitsToPoints = require_units.masterUnitsToPoints;
214
+ exports.pointsToEmu = require_units.pointsToEmu;
175
215
  exports.pointsToMasterUnits = require_units.pointsToMasterUnits;
216
+ exports.readBlipStore = require_drawing_blips.readBlipStore;
176
217
  exports.readCurrentUserAtom = require_stream_current_user.readCurrentUserAtom;
177
218
  exports.readDocumentAtom = require_document_document_atom.readDocumentAtom;
178
219
  exports.readDrawingShapes = require_drawing_shapes.readDrawingShapes;
179
220
  exports.readFontNames = require_document_fonts.readFontNames;
221
+ exports.readIMsoArray = require_drawing_properties.readIMsoArray;
180
222
  exports.readNotesAtom = require_document_notes.readNotesAtom;
181
223
  exports.readNotesContainerAtom = require_document_notes.readNotesContainerAtom;
182
224
  exports.readNotesListWithText = require_document_notes_list.readNotesListWithText;
@@ -188,6 +230,7 @@ exports.readPptStreams = require_read.readPptStreams;
188
230
  exports.readRecordAt = require_record_tree.readRecordAt;
189
231
  exports.readRecordHeader = require_record_header.readRecordHeader;
190
232
  exports.readRecordSequence = require_record_tree.readRecordSequence;
233
+ exports.readShapeProperties = require_drawing_properties.readShapeProperties;
191
234
  exports.readSlideListWithText = require_document_slide_list.readSlideListWithText;
192
235
  exports.readStyleTextPropAtom = require_text_style.readStyleTextPropAtom;
193
236
  exports.readTextBody = require_text_atoms.readTextBody;
@@ -204,8 +247,9 @@ exports.writeAtom = require_record_write.writeAtom;
204
247
  exports.writeContainer = require_record_write.writeContainer;
205
248
  exports.writeCurrentUserAtom = require_stream_current_user_write.writeCurrentUserAtom;
206
249
  exports.writeDocumentAtom = require_document_document_atom_write.writeDocumentAtom;
207
- exports.writeDrawingWithClientData = require_drawing_shapes_write.writeDrawingWithClientData;
250
+ exports.writeDrawingGroupContainer = require_drawing_blips.writeDrawingGroupContainer;
208
251
  exports.writeEnvironment = require_document_fonts_write.writeEnvironment;
252
+ exports.writeIMsoArray = require_drawing_properties.writeIMsoArray;
209
253
  exports.writeMainMaster = require_document_master_write.writeMainMaster;
210
254
  exports.writeMasterListWithText = require_document_master_write.writeMasterListWithText;
211
255
  exports.writeNotesAtom = require_document_notes_write.writeNotesAtom;
@@ -215,6 +259,7 @@ exports.writePersistDirectoryAtom = require_stream_persist_write.writePersistDir
215
259
  exports.writePpt = require_write.writePpt;
216
260
  exports.writePptContent = require_write.writePptContent;
217
261
  exports.writePptStreams = require_write.writePptStreams;
262
+ exports.writeShapePropertyTable = require_drawing_properties.writeShapePropertyTable;
218
263
  exports.writeSlideAtom = require_document_master_write.writeSlideAtom;
219
264
  exports.writeSlideAtomForSlide = require_document_master_write.writeSlideAtomForSlide;
220
265
  exports.writeSlideDrawing = require_drawing_shapes_write.writeSlideDrawing;