ppt-codec 1.5.0 → 1.6.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 (58) hide show
  1. package/README.md +70 -58
  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 +20 -15
  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 +14 -6
  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 +14 -6
  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 +94 -0
  31. package/dist/drawing/properties.d.cts +25 -0
  32. package/dist/drawing/properties.d.ts +25 -0
  33. package/dist/drawing/properties.js +83 -0
  34. package/dist/drawing/shapes-write.cjs +204 -17
  35. package/dist/drawing/shapes-write.d.cts +15 -4
  36. package/dist/drawing/shapes-write.d.ts +15 -4
  37. package/dist/drawing/shapes-write.js +206 -18
  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 +38 -1
  43. package/dist/index.d.cts +10 -6
  44. package/dist/index.d.ts +10 -6
  45. package/dist/index.js +8 -4
  46. package/dist/read.cjs +101 -19
  47. package/dist/read.d.cts +3 -2
  48. package/dist/read.d.ts +3 -2
  49. package/dist/read.js +103 -22
  50. package/dist/record/types.cjs +28 -0
  51. package/dist/record/types.d.cts +15 -1
  52. package/dist/record/types.d.ts +15 -1
  53. package/dist/record/types.js +15 -1
  54. package/dist/write.cjs +100 -37
  55. package/dist/write.d.cts +9 -4
  56. package/dist/write.d.ts +9 -4
  57. package/dist/write.js +100 -37
  58. package/package.json +2 -1
@@ -9,11 +9,13 @@ declare const RT_Environment = 1010;
9
9
  declare const RT_SlidePersistAtom = 1011;
10
10
  declare const RT_MainMaster = 1016;
11
11
  declare const RT_ExternalObjectList = 1033;
12
+ declare const RT_ExternalObjectListAtom = 1034;
12
13
  declare const RT_DrawingGroup = 1035;
13
14
  declare const RT_Drawing = 1036;
14
15
  declare const RT_List = 2000;
15
16
  declare const RT_FontCollection = 2005;
16
17
  declare const RT_ColorSchemeAtom = 2032;
18
+ declare const RT_ExternalObjectRefAtom = 3009;
17
19
  declare const RT_PlaceholderAtom = 3011;
18
20
  declare const RT_OutlineTextRefAtom = 3998;
19
21
  declare const RT_TextHeaderAtom = 3999;
@@ -27,17 +29,25 @@ declare const RT_TextSpecialInfoDefaultAtom = 4009;
27
29
  declare const RT_TextSpecialInfoAtom = 4010;
28
30
  declare const RT_FontEntityAtom = 4023;
29
31
  declare const RT_CString = 4026;
32
+ declare const RT_ExternalOleObjectAtom = 4035;
33
+ declare const RT_ExternalOleEmbed = 4044;
34
+ declare const RT_ExternalOleEmbedAtom = 4045;
30
35
  declare const RT_SlideListWithText = 4080;
31
36
  declare const RT_UserEditAtom = 4085;
32
37
  declare const RT_CurrentUserAtom = 4086;
38
+ declare const RT_ExternalOleObjectStg = 4113;
33
39
  declare const RT_PersistDirectoryAtom = 6002;
34
40
  declare const RT_CryptSession10Container = 12052;
35
41
  declare const SLIDE_LIST_INSTANCE_SLIDES = 0;
36
42
  declare const SLIDE_LIST_INSTANCE_MASTERS = 1;
37
43
  declare const SLIDE_LIST_INSTANCE_NOTES = 2;
44
+ declare const OfficeArtDggContainer = 61440;
45
+ declare const OfficeArtBStoreContainer = 61441;
38
46
  declare const OfficeArtDgContainer = 61442;
39
47
  declare const OfficeArtSpgrContainer = 61443;
40
48
  declare const OfficeArtSpContainer = 61444;
49
+ declare const OfficeArtFDGGBlock = 61446;
50
+ declare const OfficeArtFBSE = 61447;
41
51
  declare const OfficeArtFSPGR = 61449;
42
52
  declare const OfficeArtFSP = 61450;
43
53
  declare const OfficeArtFOPT = 61451;
@@ -45,5 +55,9 @@ declare const OfficeArtClientTextbox = 61453;
45
55
  declare const OfficeArtChildAnchor = 61455;
46
56
  declare const OfficeArtClientAnchor = 61456;
47
57
  declare const OfficeArtClientData = 61457;
58
+ declare const OfficeArtSecondaryFOPT = 61729;
59
+ declare const OfficeArtTertiaryFOPT = 61730;
60
+ declare const OfficeArtBlipJPEG = 61469;
61
+ declare const OfficeArtBlipPNG = 61470;
48
62
  //#endregion
49
- export { OfficeArtChildAnchor, OfficeArtClientAnchor, OfficeArtClientData, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtFOPT, OfficeArtFSP, OfficeArtFSPGR, OfficeArtSpContainer, OfficeArtSpgrContainer, RT_CString, RT_ColorSchemeAtom, RT_CryptSession10Container, RT_CurrentUserAtom, RT_Document, RT_DocumentAtom, RT_Drawing, RT_DrawingGroup, RT_Environment, RT_ExternalObjectList, RT_FontCollection, RT_FontEntityAtom, RT_List, RT_MainMaster, RT_MasterTextPropAtom, RT_Notes, RT_NotesAtom, RT_OutlineTextRefAtom, RT_PersistDirectoryAtom, RT_PlaceholderAtom, RT_Slide, RT_SlideAtom, RT_SlideListWithText, RT_SlidePersistAtom, RT_StyleTextPropAtom, RT_TextBytesAtom, RT_TextCharsAtom, RT_TextHeaderAtom, RT_TextMasterStyleAtom, RT_TextRulerAtom, RT_TextSpecialInfoAtom, RT_TextSpecialInfoDefaultAtom, RT_UserEditAtom, SLIDE_LIST_INSTANCE_MASTERS, SLIDE_LIST_INSTANCE_NOTES, SLIDE_LIST_INSTANCE_SLIDES };
63
+ export { OfficeArtBStoreContainer, OfficeArtBlipJPEG, OfficeArtBlipPNG, OfficeArtChildAnchor, OfficeArtClientAnchor, OfficeArtClientData, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtDggContainer, OfficeArtFBSE, OfficeArtFDGGBlock, OfficeArtFOPT, OfficeArtFSP, OfficeArtFSPGR, OfficeArtSecondaryFOPT, OfficeArtSpContainer, OfficeArtSpgrContainer, OfficeArtTertiaryFOPT, RT_CString, RT_ColorSchemeAtom, RT_CryptSession10Container, RT_CurrentUserAtom, RT_Document, RT_DocumentAtom, RT_Drawing, RT_DrawingGroup, RT_Environment, RT_ExternalObjectList, RT_ExternalObjectListAtom, RT_ExternalObjectRefAtom, RT_ExternalOleEmbed, RT_ExternalOleEmbedAtom, RT_ExternalOleObjectAtom, RT_ExternalOleObjectStg, RT_FontCollection, RT_FontEntityAtom, RT_List, RT_MainMaster, RT_MasterTextPropAtom, RT_Notes, RT_NotesAtom, RT_OutlineTextRefAtom, RT_PersistDirectoryAtom, RT_PlaceholderAtom, RT_Slide, RT_SlideAtom, RT_SlideListWithText, RT_SlidePersistAtom, RT_StyleTextPropAtom, RT_TextBytesAtom, RT_TextCharsAtom, RT_TextHeaderAtom, RT_TextMasterStyleAtom, RT_TextRulerAtom, RT_TextSpecialInfoAtom, RT_TextSpecialInfoDefaultAtom, RT_UserEditAtom, SLIDE_LIST_INSTANCE_MASTERS, SLIDE_LIST_INSTANCE_NOTES, SLIDE_LIST_INSTANCE_SLIDES };
@@ -9,11 +9,13 @@ const RT_Environment = 1010;
9
9
  const RT_SlidePersistAtom = 1011;
10
10
  const RT_MainMaster = 1016;
11
11
  const RT_ExternalObjectList = 1033;
12
+ const RT_ExternalObjectListAtom = 1034;
12
13
  const RT_DrawingGroup = 1035;
13
14
  const RT_Drawing = 1036;
14
15
  const RT_List = 2e3;
15
16
  const RT_FontCollection = 2005;
16
17
  const RT_ColorSchemeAtom = 2032;
18
+ const RT_ExternalObjectRefAtom = 3009;
17
19
  const RT_PlaceholderAtom = 3011;
18
20
  const RT_OutlineTextRefAtom = 3998;
19
21
  const RT_TextHeaderAtom = 3999;
@@ -27,17 +29,25 @@ const RT_TextSpecialInfoDefaultAtom = 4009;
27
29
  const RT_TextSpecialInfoAtom = 4010;
28
30
  const RT_FontEntityAtom = 4023;
29
31
  const RT_CString = 4026;
32
+ const RT_ExternalOleObjectAtom = 4035;
33
+ const RT_ExternalOleEmbed = 4044;
34
+ const RT_ExternalOleEmbedAtom = 4045;
30
35
  const RT_SlideListWithText = 4080;
31
36
  const RT_UserEditAtom = 4085;
32
37
  const RT_CurrentUserAtom = 4086;
38
+ const RT_ExternalOleObjectStg = 4113;
33
39
  const RT_PersistDirectoryAtom = 6002;
34
40
  const RT_CryptSession10Container = 12052;
35
41
  const SLIDE_LIST_INSTANCE_SLIDES = 0;
36
42
  const SLIDE_LIST_INSTANCE_MASTERS = 1;
37
43
  const SLIDE_LIST_INSTANCE_NOTES = 2;
44
+ const OfficeArtDggContainer = 61440;
45
+ const OfficeArtBStoreContainer = 61441;
38
46
  const OfficeArtDgContainer = 61442;
39
47
  const OfficeArtSpgrContainer = 61443;
40
48
  const OfficeArtSpContainer = 61444;
49
+ const OfficeArtFDGGBlock = 61446;
50
+ const OfficeArtFBSE = 61447;
41
51
  const OfficeArtFSPGR = 61449;
42
52
  const OfficeArtFSP = 61450;
43
53
  const OfficeArtFOPT = 61451;
@@ -45,5 +55,9 @@ const OfficeArtClientTextbox = 61453;
45
55
  const OfficeArtChildAnchor = 61455;
46
56
  const OfficeArtClientAnchor = 61456;
47
57
  const OfficeArtClientData = 61457;
58
+ const OfficeArtSecondaryFOPT = 61729;
59
+ const OfficeArtTertiaryFOPT = 61730;
60
+ const OfficeArtBlipJPEG = 61469;
61
+ const OfficeArtBlipPNG = 61470;
48
62
  //#endregion
49
- export { OfficeArtChildAnchor, OfficeArtClientAnchor, OfficeArtClientData, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtFOPT, OfficeArtFSP, OfficeArtFSPGR, OfficeArtSpContainer, OfficeArtSpgrContainer, RT_CString, RT_ColorSchemeAtom, RT_CryptSession10Container, RT_CurrentUserAtom, RT_Document, RT_DocumentAtom, RT_Drawing, RT_DrawingGroup, RT_Environment, RT_ExternalObjectList, RT_FontCollection, RT_FontEntityAtom, RT_List, RT_MainMaster, RT_MasterTextPropAtom, RT_Notes, RT_NotesAtom, RT_OutlineTextRefAtom, RT_PersistDirectoryAtom, RT_PlaceholderAtom, RT_Slide, RT_SlideAtom, RT_SlideListWithText, RT_SlidePersistAtom, RT_StyleTextPropAtom, RT_TextBytesAtom, RT_TextCharsAtom, RT_TextHeaderAtom, RT_TextMasterStyleAtom, RT_TextRulerAtom, RT_TextSpecialInfoAtom, RT_TextSpecialInfoDefaultAtom, RT_UserEditAtom, SLIDE_LIST_INSTANCE_MASTERS, SLIDE_LIST_INSTANCE_NOTES, SLIDE_LIST_INSTANCE_SLIDES };
63
+ export { OfficeArtBStoreContainer, OfficeArtBlipJPEG, OfficeArtBlipPNG, OfficeArtChildAnchor, OfficeArtClientAnchor, OfficeArtClientData, OfficeArtClientTextbox, OfficeArtDgContainer, OfficeArtDggContainer, OfficeArtFBSE, OfficeArtFDGGBlock, OfficeArtFOPT, OfficeArtFSP, OfficeArtFSPGR, OfficeArtSecondaryFOPT, OfficeArtSpContainer, OfficeArtSpgrContainer, OfficeArtTertiaryFOPT, RT_CString, RT_ColorSchemeAtom, RT_CryptSession10Container, RT_CurrentUserAtom, RT_Document, RT_DocumentAtom, RT_Drawing, RT_DrawingGroup, RT_Environment, RT_ExternalObjectList, RT_ExternalObjectListAtom, RT_ExternalObjectRefAtom, RT_ExternalOleEmbed, RT_ExternalOleEmbedAtom, RT_ExternalOleObjectAtom, RT_ExternalOleObjectStg, RT_FontCollection, RT_FontEntityAtom, RT_List, RT_MainMaster, RT_MasterTextPropAtom, RT_Notes, RT_NotesAtom, RT_OutlineTextRefAtom, RT_PersistDirectoryAtom, RT_PlaceholderAtom, RT_Slide, RT_SlideAtom, RT_SlideListWithText, RT_SlidePersistAtom, RT_StyleTextPropAtom, RT_TextBytesAtom, RT_TextCharsAtom, RT_TextHeaderAtom, RT_TextMasterStyleAtom, RT_TextRulerAtom, RT_TextSpecialInfoAtom, RT_TextSpecialInfoDefaultAtom, RT_UserEditAtom, SLIDE_LIST_INSTANCE_MASTERS, SLIDE_LIST_INSTANCE_NOTES, SLIDE_LIST_INSTANCE_SLIDES };
package/dist/write.cjs CHANGED
@@ -1,10 +1,13 @@
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_types = require("./record/types.cjs");
4
5
  const require_content_write = require("./content-write.cjs");
6
+ const require_diagnostics = require("./diagnostics.cjs");
5
7
  const require_record_write = require("./record/write.cjs");
6
8
  const require_document_document_atom_write = require("./document/document-atom-write.cjs");
7
9
  const require_document_fonts_write = require("./document/fonts-write.cjs");
10
+ const require_drawing_blips = require("./drawing/blips.cjs");
8
11
  const require_drawing_shapes_write = require("./drawing/shapes-write.cjs");
9
12
  const require_read = require("./read.cjs");
10
13
  const require_document_master_write = require("./document/master-write.cjs");
@@ -32,65 +35,125 @@ function requireOneSlideSize(slides) {
32
35
  for (const slide of slides) if (slide.size.widthPt !== first.widthPt || slide.size.heightPt !== first.heightPt) throw new require_errors.PptUnsupportedContentError(`ppt-codec's writer cannot express per-slide sizes: slide sizes ${JSON.stringify(first)} and ${JSON.stringify(slide.size)} both appear, but [MS-PPT]'s DocumentAtom states exactly one slide size for the whole presentation`);
33
36
  return first;
34
37
  }
35
- function writeSlideContainer(shapes, notesIdRef, fontIndexOf) {
36
- return require_record_write.writeContainer(require_record_types.RT_Slide, [require_document_master_write.writeSlideAtomForSlide(notesIdRef), require_drawing_shapes_write.writeSlideDrawing(shapes, fontIndexOf)]);
38
+ function writeSlideContainer(shapes, notesIdRef, context) {
39
+ const drawing = require_drawing_shapes_write.writeSlideDrawing(shapes.map((shape) => ({
40
+ shape,
41
+ clientData: void 0
42
+ })), context);
43
+ return {
44
+ bytes: require_record_write.writeContainer(require_record_types.RT_Slide, [require_document_master_write.writeSlideAtomForSlide(notesIdRef), drawing.bytes]),
45
+ shapeCount: drawing.shapeCount,
46
+ maxSpid: drawing.maxSpid
47
+ };
37
48
  }
38
- function writePptStreams(document) {
49
+ function planBlipStore(slides) {
50
+ const blips = [];
51
+ const pibByKey = /* @__PURE__ */ new Map();
52
+ for (const slide of slides) for (const shape of slide.shapes) for (const block of shape.blocks) {
53
+ if (block.kind !== "image" || !require_drawing_blips.isBlipFormat(block.format)) continue;
54
+ const key = `${block.format}:${block.base64}`;
55
+ if (!pibByKey.has(key)) {
56
+ pibByKey.set(key, blips.length + 1);
57
+ blips.push({
58
+ format: block.format,
59
+ bytes: require_base64.base64ToBytes(block.base64)
60
+ });
61
+ }
62
+ }
63
+ return {
64
+ blips,
65
+ pibOf: (image) => {
66
+ const pib = pibByKey.get(`${image.format}:${image.base64}`);
67
+ if (pib === void 0) throw new require_errors.PptUnsupportedContentError("internal error: an image block reached the drawing writer without first being collected into the document's blip store");
68
+ return pib;
69
+ }
70
+ };
71
+ }
72
+ function writePptStreams(document, options = {}) {
73
+ options.signal?.throwIfAborted();
39
74
  const { slides } = document;
40
75
  const size = requireOneSlideSize(slides);
76
+ const sink = options.sink ?? require_diagnostics.NOOP_PPT_DIAGNOSTIC_SINK;
41
77
  const fontNames = require_content_write.collectFontFamilies(slides.map((slide) => slide.shapes.flatMap((shape) => shape.blocks)));
42
78
  const fontIndexOf = (family) => {
43
79
  const index = fontNames.indexOf(family);
44
80
  if (index === -1) throw new require_errors.PptUnsupportedContentError(`font family '${family}' was not collected into the document's font table before writing`);
45
81
  return index;
46
82
  };
83
+ const store = planBlipStore(slides);
84
+ const contextFor = (location) => ({
85
+ fontIndexOf,
86
+ blipIndexOf: store.pibOf,
87
+ sink,
88
+ location
89
+ });
47
90
  const slidePersistRefs = slides.map((_slide, index) => ({
48
91
  persistIdRef: FIRST_SLIDE_PERSIST_ID + index,
49
92
  slideId: FIRST_SLIDE_ID + index
50
93
  }));
94
+ const notesIdRefs = slides.map((slide, index) => slide.notes.length === 0 ? NO_NOTES_ID_REF : FIRST_NOTES_ID + slides.slice(0, index).filter((earlier) => earlier.notes.length > 0).length);
95
+ let shapeCount = 0;
96
+ let maxSpid = 0;
97
+ let drawingCount = 0;
98
+ const account = (drawing) => {
99
+ shapeCount += drawing.shapeCount;
100
+ maxSpid = Math.max(maxSpid, drawing.maxSpid);
101
+ drawingCount += 1;
102
+ };
103
+ const mainMaster = require_document_master_write.writeMainMaster(size, contextFor("the main master"));
104
+ account(mainMaster);
105
+ const slideContainers = slides.map((slide, index) => {
106
+ const ref = slidePersistRefs[index];
107
+ const notesIdRef = notesIdRefs[index];
108
+ if (ref === void 0 || notesIdRef === void 0) throw new require_errors.PptUnsupportedContentError("internal error: slide persist reference missing for a slide being written");
109
+ const container = writeSlideContainer(slide.shapes, notesIdRef, contextFor(`slide ${index + 1}`));
110
+ account(container);
111
+ return {
112
+ persistId: ref.persistIdRef,
113
+ bytes: container.bytes
114
+ };
115
+ });
51
116
  const notesPersists = [];
52
117
  const notesContainers = [];
53
- const notesIdRefs = slides.map((slide, index) => {
54
- if (slide.notes.length === 0) return NO_NOTES_ID_REF;
55
- const notesId = FIRST_NOTES_ID + notesPersists.length;
118
+ slides.forEach((slide, index) => {
119
+ const notesId = notesIdRefs[index];
120
+ if (notesId === void 0 || notesId === NO_NOTES_ID_REF) return;
121
+ const persistIdRef = FIRST_SLIDE_PERSIST_ID + slides.length + notesPersists.length;
56
122
  notesPersists.push({
57
- persistIdRef: FIRST_SLIDE_PERSIST_ID + slides.length + notesPersists.length,
123
+ persistIdRef,
58
124
  notesId
59
125
  });
60
- notesContainers.push(require_document_notes_write.writeNotesContainer(FIRST_SLIDE_ID + index, slide.notes, size, fontIndexOf));
61
- return notesId;
126
+ const container = require_document_notes_write.writeNotesContainer(FIRST_SLIDE_ID + index, slide.notes, size, contextFor(`slide ${index + 1}'s speaker notes`));
127
+ account(container);
128
+ notesContainers.push({
129
+ persistId: persistIdRef,
130
+ bytes: container.bytes
131
+ });
62
132
  });
63
133
  const environment = require_document_fonts_write.writeEnvironment(fontNames);
64
134
  const documentChildren = [require_document_document_atom_write.writeDocumentAtom(size)];
65
135
  if (environment !== void 0) documentChildren.push(environment);
136
+ documentChildren.push(require_drawing_blips.writeDrawingGroupContainer(store.blips, {
137
+ spidMax: maxSpid,
138
+ shapeCount,
139
+ drawingCount
140
+ }));
66
141
  documentChildren.push(require_document_master_write.writeMasterListWithText(MASTER_PERSIST_ID));
67
142
  documentChildren.push(require_document_slide_list_write.writeSlideListWithText(slidePersistRefs));
68
143
  if (notesPersists.length > 0) documentChildren.push(require_document_notes_list_write.writeNotesListWithText(notesPersists));
69
144
  const documentContainer = require_record_write.writeContainer(require_record_types.RT_Document, documentChildren);
70
- const persistObjects = [{
71
- persistId: DOCUMENT_PERSIST_ID,
72
- bytes: documentContainer
73
- }, {
74
- persistId: MASTER_PERSIST_ID,
75
- bytes: require_document_master_write.writeMainMaster(size, fontIndexOf)
76
- }];
77
- slides.forEach((slide, index) => {
78
- const ref = slidePersistRefs[index];
79
- const notesIdRef = notesIdRefs[index];
80
- if (ref === void 0 || notesIdRef === void 0) throw new require_errors.PptUnsupportedContentError("internal error: slide persist reference missing for a slide being written");
81
- persistObjects.push({
82
- persistId: ref.persistIdRef,
83
- bytes: writeSlideContainer(slide.shapes, notesIdRef, fontIndexOf)
84
- });
85
- });
86
- notesPersists.forEach((persist, index) => {
87
- const bytes = notesContainers[index];
88
- if (bytes === void 0) throw new require_errors.PptUnsupportedContentError("internal error: notes container missing for a notes persist reference");
89
- persistObjects.push({
90
- persistId: persist.persistIdRef,
91
- bytes
92
- });
93
- });
145
+ const persistObjects = [
146
+ {
147
+ persistId: DOCUMENT_PERSIST_ID,
148
+ bytes: documentContainer
149
+ },
150
+ {
151
+ persistId: MASTER_PERSIST_ID,
152
+ bytes: mainMaster.bytes
153
+ },
154
+ ...slideContainers,
155
+ ...notesContainers
156
+ ];
94
157
  const persistEntries = [];
95
158
  let offset = 0;
96
159
  for (const object of persistObjects) {
@@ -116,8 +179,8 @@ function writePptStreams(document) {
116
179
  powerPointDocumentStream: require_record_write.concatBytes(...persistObjects.map((object) => object.bytes), persistDirectory, userEdit)
117
180
  };
118
181
  }
119
- function writePptContent(document) {
120
- const { currentUserStream, powerPointDocumentStream } = writePptStreams(document);
182
+ function writePptContent(document, options = {}) {
183
+ const { currentUserStream, powerPointDocumentStream } = writePptStreams(document, options);
121
184
  const streams = [{
122
185
  path: require_read.CURRENT_USER_STREAM,
123
186
  bytes: currentUserStream
@@ -131,13 +194,13 @@ function writePptContent(document) {
131
194
  });
132
195
  return (0, archive_codec.writeCompoundFile)(streams);
133
196
  }
134
- function writePpt(tree) {
197
+ function writePpt(tree, options = {}) {
135
198
  const content = (0, document_schema_js.flattenTree)(tree);
136
199
  if (content.kind !== "presentation") throw new require_errors.PptUnsupportedContentError(`ppt-codec's writer only writes presentation documents; got a '${content.kind}' document`);
137
200
  return writePptContent({
138
201
  metadata: content.metadata,
139
202
  slides: content.slides
140
- });
203
+ }, options);
141
204
  }
142
205
  //#endregion
143
206
  exports.writePpt = writePpt;
package/dist/write.d.cts CHANGED
@@ -1,11 +1,16 @@
1
+ import { a as PptDiagnosticSink } from "./diagnostics-CqxAnubw.cjs";
1
2
  import { PptDocument } from "./read.cjs";
2
3
  import { DocumentTree } from "document-schema.js";
3
4
  //#region src/write.d.ts
4
- declare function writePptStreams(document: PptDocument): {
5
+ interface WritePptOptions {
6
+ readonly signal?: AbortSignal;
7
+ readonly sink?: PptDiagnosticSink;
8
+ }
9
+ declare function writePptStreams(document: PptDocument, options?: WritePptOptions): {
5
10
  readonly currentUserStream: Uint8Array<ArrayBuffer>;
6
11
  readonly powerPointDocumentStream: Uint8Array<ArrayBuffer>;
7
12
  };
8
- declare function writePptContent(document: PptDocument): Uint8Array<ArrayBuffer>;
9
- declare function writePpt(tree: DocumentTree): Uint8Array<ArrayBuffer>;
13
+ declare function writePptContent(document: PptDocument, options?: WritePptOptions): Uint8Array<ArrayBuffer>;
14
+ declare function writePpt(tree: DocumentTree, options?: WritePptOptions): Uint8Array<ArrayBuffer>;
10
15
  //#endregion
11
- export { writePpt, writePptContent, writePptStreams };
16
+ export { WritePptOptions, writePpt, writePptContent, writePptStreams };
package/dist/write.d.ts CHANGED
@@ -1,11 +1,16 @@
1
+ import { a as PptDiagnosticSink } from "./diagnostics-CqxAnubw.js";
1
2
  import { PptDocument } from "./read.js";
2
3
  import { DocumentTree } from "document-schema.js";
3
4
  //#region src/write.d.ts
4
- declare function writePptStreams(document: PptDocument): {
5
+ interface WritePptOptions {
6
+ readonly signal?: AbortSignal;
7
+ readonly sink?: PptDiagnosticSink;
8
+ }
9
+ declare function writePptStreams(document: PptDocument, options?: WritePptOptions): {
5
10
  readonly currentUserStream: Uint8Array<ArrayBuffer>;
6
11
  readonly powerPointDocumentStream: Uint8Array<ArrayBuffer>;
7
12
  };
8
- declare function writePptContent(document: PptDocument): Uint8Array<ArrayBuffer>;
9
- declare function writePpt(tree: DocumentTree): Uint8Array<ArrayBuffer>;
13
+ declare function writePptContent(document: PptDocument, options?: WritePptOptions): Uint8Array<ArrayBuffer>;
14
+ declare function writePpt(tree: DocumentTree, options?: WritePptOptions): Uint8Array<ArrayBuffer>;
10
15
  //#endregion
11
- export { writePpt, writePptContent, writePptStreams };
16
+ export { WritePptOptions, writePpt, writePptContent, writePptStreams };
package/dist/write.js CHANGED
@@ -1,9 +1,12 @@
1
+ import { base64ToBytes } from "./base64.js";
1
2
  import { PptUnsupportedContentError } from "./errors.js";
2
3
  import { RT_Document, RT_Slide } from "./record/types.js";
3
4
  import { collectFontFamilies } from "./content-write.js";
5
+ import { NOOP_PPT_DIAGNOSTIC_SINK } from "./diagnostics.js";
4
6
  import { concatBytes, writeContainer } from "./record/write.js";
5
7
  import { writeDocumentAtom } from "./document/document-atom-write.js";
6
8
  import { writeEnvironment } from "./document/fonts-write.js";
9
+ import { isBlipFormat, writeDrawingGroupContainer } from "./drawing/blips.js";
7
10
  import { writeSlideDrawing } from "./drawing/shapes-write.js";
8
11
  import { CURRENT_USER_STREAM, POWERPOINT_DOCUMENT_STREAM, SUMMARY_INFORMATION_STREAM } from "./read.js";
9
12
  import { writeMainMaster, writeMasterListWithText, writeSlideAtomForSlide } from "./document/master-write.js";
@@ -31,65 +34,125 @@ function requireOneSlideSize(slides) {
31
34
  for (const slide of slides) if (slide.size.widthPt !== first.widthPt || slide.size.heightPt !== first.heightPt) throw new PptUnsupportedContentError(`ppt-codec's writer cannot express per-slide sizes: slide sizes ${JSON.stringify(first)} and ${JSON.stringify(slide.size)} both appear, but [MS-PPT]'s DocumentAtom states exactly one slide size for the whole presentation`);
32
35
  return first;
33
36
  }
34
- function writeSlideContainer(shapes, notesIdRef, fontIndexOf) {
35
- return writeContainer(RT_Slide, [writeSlideAtomForSlide(notesIdRef), writeSlideDrawing(shapes, fontIndexOf)]);
37
+ function writeSlideContainer(shapes, notesIdRef, context) {
38
+ const drawing = writeSlideDrawing(shapes.map((shape) => ({
39
+ shape,
40
+ clientData: void 0
41
+ })), context);
42
+ return {
43
+ bytes: writeContainer(RT_Slide, [writeSlideAtomForSlide(notesIdRef), drawing.bytes]),
44
+ shapeCount: drawing.shapeCount,
45
+ maxSpid: drawing.maxSpid
46
+ };
36
47
  }
37
- function writePptStreams(document) {
48
+ function planBlipStore(slides) {
49
+ const blips = [];
50
+ const pibByKey = /* @__PURE__ */ new Map();
51
+ for (const slide of slides) for (const shape of slide.shapes) for (const block of shape.blocks) {
52
+ if (block.kind !== "image" || !isBlipFormat(block.format)) continue;
53
+ const key = `${block.format}:${block.base64}`;
54
+ if (!pibByKey.has(key)) {
55
+ pibByKey.set(key, blips.length + 1);
56
+ blips.push({
57
+ format: block.format,
58
+ bytes: base64ToBytes(block.base64)
59
+ });
60
+ }
61
+ }
62
+ return {
63
+ blips,
64
+ pibOf: (image) => {
65
+ const pib = pibByKey.get(`${image.format}:${image.base64}`);
66
+ if (pib === void 0) throw new PptUnsupportedContentError("internal error: an image block reached the drawing writer without first being collected into the document's blip store");
67
+ return pib;
68
+ }
69
+ };
70
+ }
71
+ function writePptStreams(document, options = {}) {
72
+ options.signal?.throwIfAborted();
38
73
  const { slides } = document;
39
74
  const size = requireOneSlideSize(slides);
75
+ const sink = options.sink ?? NOOP_PPT_DIAGNOSTIC_SINK;
40
76
  const fontNames = collectFontFamilies(slides.map((slide) => slide.shapes.flatMap((shape) => shape.blocks)));
41
77
  const fontIndexOf = (family) => {
42
78
  const index = fontNames.indexOf(family);
43
79
  if (index === -1) throw new PptUnsupportedContentError(`font family '${family}' was not collected into the document's font table before writing`);
44
80
  return index;
45
81
  };
82
+ const store = planBlipStore(slides);
83
+ const contextFor = (location) => ({
84
+ fontIndexOf,
85
+ blipIndexOf: store.pibOf,
86
+ sink,
87
+ location
88
+ });
46
89
  const slidePersistRefs = slides.map((_slide, index) => ({
47
90
  persistIdRef: FIRST_SLIDE_PERSIST_ID + index,
48
91
  slideId: FIRST_SLIDE_ID + index
49
92
  }));
93
+ const notesIdRefs = slides.map((slide, index) => slide.notes.length === 0 ? NO_NOTES_ID_REF : FIRST_NOTES_ID + slides.slice(0, index).filter((earlier) => earlier.notes.length > 0).length);
94
+ let shapeCount = 0;
95
+ let maxSpid = 0;
96
+ let drawingCount = 0;
97
+ const account = (drawing) => {
98
+ shapeCount += drawing.shapeCount;
99
+ maxSpid = Math.max(maxSpid, drawing.maxSpid);
100
+ drawingCount += 1;
101
+ };
102
+ const mainMaster = writeMainMaster(size, contextFor("the main master"));
103
+ account(mainMaster);
104
+ const slideContainers = slides.map((slide, index) => {
105
+ const ref = slidePersistRefs[index];
106
+ const notesIdRef = notesIdRefs[index];
107
+ if (ref === void 0 || notesIdRef === void 0) throw new PptUnsupportedContentError("internal error: slide persist reference missing for a slide being written");
108
+ const container = writeSlideContainer(slide.shapes, notesIdRef, contextFor(`slide ${index + 1}`));
109
+ account(container);
110
+ return {
111
+ persistId: ref.persistIdRef,
112
+ bytes: container.bytes
113
+ };
114
+ });
50
115
  const notesPersists = [];
51
116
  const notesContainers = [];
52
- const notesIdRefs = slides.map((slide, index) => {
53
- if (slide.notes.length === 0) return NO_NOTES_ID_REF;
54
- const notesId = FIRST_NOTES_ID + notesPersists.length;
117
+ slides.forEach((slide, index) => {
118
+ const notesId = notesIdRefs[index];
119
+ if (notesId === void 0 || notesId === NO_NOTES_ID_REF) return;
120
+ const persistIdRef = FIRST_SLIDE_PERSIST_ID + slides.length + notesPersists.length;
55
121
  notesPersists.push({
56
- persistIdRef: FIRST_SLIDE_PERSIST_ID + slides.length + notesPersists.length,
122
+ persistIdRef,
57
123
  notesId
58
124
  });
59
- notesContainers.push(writeNotesContainer(FIRST_SLIDE_ID + index, slide.notes, size, fontIndexOf));
60
- return notesId;
125
+ const container = writeNotesContainer(FIRST_SLIDE_ID + index, slide.notes, size, contextFor(`slide ${index + 1}'s speaker notes`));
126
+ account(container);
127
+ notesContainers.push({
128
+ persistId: persistIdRef,
129
+ bytes: container.bytes
130
+ });
61
131
  });
62
132
  const environment = writeEnvironment(fontNames);
63
133
  const documentChildren = [writeDocumentAtom(size)];
64
134
  if (environment !== void 0) documentChildren.push(environment);
135
+ documentChildren.push(writeDrawingGroupContainer(store.blips, {
136
+ spidMax: maxSpid,
137
+ shapeCount,
138
+ drawingCount
139
+ }));
65
140
  documentChildren.push(writeMasterListWithText(MASTER_PERSIST_ID));
66
141
  documentChildren.push(writeSlideListWithText(slidePersistRefs));
67
142
  if (notesPersists.length > 0) documentChildren.push(writeNotesListWithText(notesPersists));
68
143
  const documentContainer = writeContainer(RT_Document, documentChildren);
69
- const persistObjects = [{
70
- persistId: DOCUMENT_PERSIST_ID,
71
- bytes: documentContainer
72
- }, {
73
- persistId: MASTER_PERSIST_ID,
74
- bytes: writeMainMaster(size, fontIndexOf)
75
- }];
76
- slides.forEach((slide, index) => {
77
- const ref = slidePersistRefs[index];
78
- const notesIdRef = notesIdRefs[index];
79
- if (ref === void 0 || notesIdRef === void 0) throw new PptUnsupportedContentError("internal error: slide persist reference missing for a slide being written");
80
- persistObjects.push({
81
- persistId: ref.persistIdRef,
82
- bytes: writeSlideContainer(slide.shapes, notesIdRef, fontIndexOf)
83
- });
84
- });
85
- notesPersists.forEach((persist, index) => {
86
- const bytes = notesContainers[index];
87
- if (bytes === void 0) throw new PptUnsupportedContentError("internal error: notes container missing for a notes persist reference");
88
- persistObjects.push({
89
- persistId: persist.persistIdRef,
90
- bytes
91
- });
92
- });
144
+ const persistObjects = [
145
+ {
146
+ persistId: DOCUMENT_PERSIST_ID,
147
+ bytes: documentContainer
148
+ },
149
+ {
150
+ persistId: MASTER_PERSIST_ID,
151
+ bytes: mainMaster.bytes
152
+ },
153
+ ...slideContainers,
154
+ ...notesContainers
155
+ ];
93
156
  const persistEntries = [];
94
157
  let offset = 0;
95
158
  for (const object of persistObjects) {
@@ -115,8 +178,8 @@ function writePptStreams(document) {
115
178
  powerPointDocumentStream: concatBytes(...persistObjects.map((object) => object.bytes), persistDirectory, userEdit)
116
179
  };
117
180
  }
118
- function writePptContent(document) {
119
- const { currentUserStream, powerPointDocumentStream } = writePptStreams(document);
181
+ function writePptContent(document, options = {}) {
182
+ const { currentUserStream, powerPointDocumentStream } = writePptStreams(document, options);
120
183
  const streams = [{
121
184
  path: CURRENT_USER_STREAM,
122
185
  bytes: currentUserStream
@@ -130,13 +193,13 @@ function writePptContent(document) {
130
193
  });
131
194
  return writeCompoundFile(streams);
132
195
  }
133
- function writePpt(tree) {
196
+ function writePpt(tree, options = {}) {
134
197
  const content = flattenTree(tree);
135
198
  if (content.kind !== "presentation") throw new PptUnsupportedContentError(`ppt-codec's writer only writes presentation documents; got a '${content.kind}' document`);
136
199
  return writePptContent({
137
200
  metadata: content.metadata,
138
201
  slides: content.slides
139
- });
202
+ }, options);
140
203
  }
141
204
  //#endregion
142
205
  export { writePpt, writePptContent, writePptStreams };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ppt-codec",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Hand-written PowerPoint 97-2003 binary (.ppt, [MS-PPT]) reader and writer against the shared document-schema.js content pivot.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -88,6 +88,7 @@
88
88
  "@stryker-mutator/typescript-checker": "10.0.0",
89
89
  "@stryker-mutator/vitest-runner": "10.0.0",
90
90
  "@types/node": "26.2.0",
91
+ "byte-codec": "1.5.0",
91
92
  "eslint": "10.8.1",
92
93
  "husky": "9.1.7",
93
94
  "jiti": "2.7.0",