ppt-codec 1.2.13 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -17
- package/dist/content-write.cjs +6 -3
- package/dist/content-write.js +6 -3
- package/dist/content.cjs +24 -14
- package/dist/content.d.cts +3 -2
- package/dist/content.d.ts +3 -2
- package/dist/content.js +24 -14
- package/dist/document/color-scheme.cjs +37 -0
- package/dist/document/color-scheme.d.cts +8 -0
- package/dist/document/color-scheme.d.ts +8 -0
- package/dist/document/color-scheme.js +35 -0
- package/dist/document/master.cjs +82 -0
- package/dist/document/master.d.cts +2 -0
- package/dist/document/master.d.ts +2 -0
- package/dist/document/master.js +78 -0
- package/dist/encryption.cjs +82 -0
- package/dist/encryption.d.cts +20 -0
- package/dist/encryption.d.ts +20 -0
- package/dist/encryption.js +80 -0
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/master-Cs_sDM1-.d.ts +25 -0
- package/dist/master-zlMRXyPU.d.cts +25 -0
- package/dist/read.cjs +70 -17
- package/dist/read.d.cts +3 -3
- package/dist/read.d.ts +3 -3
- package/dist/read.js +73 -20
- package/dist/text/style-write.cjs +10 -4
- package/dist/text/style-write.js +10 -4
- package/dist/text/style.cjs +43 -5
- package/dist/text/style.d.cts +20 -2
- package/dist/text/style.d.ts +20 -2
- package/dist/text/style.js +42 -7
- package/package.json +2 -2
package/dist/read.cjs
CHANGED
|
@@ -5,7 +5,10 @@ const require_record_types = require("./record/types.cjs");
|
|
|
5
5
|
const require_text_style = require("./text/style.cjs");
|
|
6
6
|
const require_text_atoms = require("./text/atoms.cjs");
|
|
7
7
|
const require_units = require("./units.cjs");
|
|
8
|
+
const require_document_color_scheme = require("./document/color-scheme.cjs");
|
|
9
|
+
const require_document_master = require("./document/master.cjs");
|
|
8
10
|
const require_content = require("./content.cjs");
|
|
11
|
+
const require_encryption = require("./encryption.cjs");
|
|
9
12
|
const require_document_document_atom = require("./document/document-atom.cjs");
|
|
10
13
|
const require_document_fonts = require("./document/fonts.cjs");
|
|
11
14
|
const require_document_notes_list = require("./document/notes-list.cjs");
|
|
@@ -35,21 +38,31 @@ function requireStream(streams, name) {
|
|
|
35
38
|
function textRecordsFor(clientTextbox, persist) {
|
|
36
39
|
const children = require_record_tree.childRecords(clientTextbox);
|
|
37
40
|
const outlineRef = require_record_tree.findChild(children, require_record_types.RT_OutlineTextRefAtom);
|
|
38
|
-
if (outlineRef === void 0)
|
|
41
|
+
if (outlineRef === void 0) {
|
|
42
|
+
const headerRecord = require_record_tree.findChild(children, require_record_types.RT_TextHeaderAtom);
|
|
43
|
+
if (headerRecord === void 0) throw new require_errors.PptFormatError("a client textbox's own text records carry no TextHeaderAtom, which [MS-PPT] 2.9.1 requires to precede its TextCharsAtom/TextBytesAtom");
|
|
44
|
+
return {
|
|
45
|
+
textType: require_text_atoms.readTextHeaderAtom(headerRecord),
|
|
46
|
+
records: children
|
|
47
|
+
};
|
|
48
|
+
}
|
|
39
49
|
if (outlineRef.data.length < 4) throw new require_errors.PptFormatError(`OutlineTextRefAtom at offset ${outlineRef.offset} carries ${outlineRef.data.length} bytes, fewer than the 4 its index field needs`);
|
|
40
50
|
const index = new DataView(outlineRef.data.buffer, outlineRef.data.byteOffset, outlineRef.data.byteLength).getInt32(0, true);
|
|
41
51
|
const outlineText = persist.texts[index];
|
|
42
52
|
if (outlineText === void 0) throw new require_errors.PptFormatError(`OutlineTextRefAtom references text ${index} of slide ${persist.slideId}, which has only ${persist.texts.length} texts in the slide list`);
|
|
43
|
-
return
|
|
53
|
+
return {
|
|
54
|
+
textType: outlineText.textType,
|
|
55
|
+
records: outlineText.records
|
|
56
|
+
};
|
|
44
57
|
}
|
|
45
|
-
function blocksFor(clientTextbox, persist, fontNames) {
|
|
58
|
+
function blocksFor(clientTextbox, persist, fontNames, masterInfo) {
|
|
46
59
|
if (clientTextbox === void 0) return [];
|
|
47
|
-
const records = textRecordsFor(clientTextbox, persist);
|
|
60
|
+
const { textType, records } = textRecordsFor(clientTextbox, persist);
|
|
48
61
|
const text = require_text_atoms.readTextBody(records);
|
|
49
62
|
if (text === void 0) return [];
|
|
50
63
|
const styleRecord = require_record_tree.findChild(records, require_record_types.RT_StyleTextPropAtom);
|
|
51
64
|
const style = styleRecord === void 0 ? NO_STYLE : require_text_style.readStyleTextPropAtom(styleRecord, require_text_atoms.characterCountOf(text));
|
|
52
|
-
return require_content.buildParagraphs(text, style, fontNames);
|
|
65
|
+
return require_content.buildParagraphs(text, style, fontNames, masterInfo.styles, textType, masterInfo.colorScheme);
|
|
53
66
|
}
|
|
54
67
|
function readNotesBySlideId(streamBytes, directory, notesList) {
|
|
55
68
|
const notes = /* @__PURE__ */ new Map();
|
|
@@ -60,10 +73,42 @@ function readNotesBySlideId(streamBytes, directory, notesList) {
|
|
|
60
73
|
}
|
|
61
74
|
return notes;
|
|
62
75
|
}
|
|
63
|
-
function
|
|
76
|
+
function colorSchemeFor(slideChildren, master) {
|
|
77
|
+
const ownScheme = require_record_tree.findChild(slideChildren, require_record_types.RT_ColorSchemeAtom);
|
|
78
|
+
return ownScheme === void 0 ? master.colorScheme : require_document_color_scheme.readSlideSchemeColorSchemeAtom(ownScheme);
|
|
79
|
+
}
|
|
80
|
+
function readMastersById(streamBytes, directory, masterList, documentDefault) {
|
|
81
|
+
const mastersById = /* @__PURE__ */ new Map();
|
|
82
|
+
if (masterList === void 0) return mastersById;
|
|
83
|
+
for (const persist of require_document_slide_list.readSlideListWithText(masterList)) {
|
|
84
|
+
const masterContainer = require_stream_persist.resolvePersistObject(streamBytes, directory, persist.persistIdRef, `MasterPersistAtom for master ${persist.slideId}`);
|
|
85
|
+
if (masterContainer.header.recType !== 1016) throw new require_errors.PptFormatError(`persist object ${persist.persistIdRef} is record type 0x${masterContainer.header.recType.toString(16)}, not the RT_MainMaster (0x${require_record_types.RT_MainMaster.toString(16)}) its MasterPersistAtom promised`);
|
|
86
|
+
const masterChildren = require_record_tree.childRecords(masterContainer);
|
|
87
|
+
const masterAtoms = masterChildren.filter((record) => record.header.recType === require_record_types.RT_TextMasterStyleAtom).map(require_text_style.readTextMasterStyleAtom);
|
|
88
|
+
const styles = require_document_master.buildMasterStyleTable(masterAtoms, documentDefault);
|
|
89
|
+
const colorSchemeRecord = require_record_tree.findChild(masterChildren, require_record_types.RT_ColorSchemeAtom);
|
|
90
|
+
if (colorSchemeRecord === void 0) throw new require_errors.PptFormatError(`MainMasterContainer for master ${persist.slideId} has no SlideSchemeColorSchemeAtom, which [MS-PPT] 2.5.3 requires`);
|
|
91
|
+
mastersById.set(persist.slideId, {
|
|
92
|
+
styles,
|
|
93
|
+
colorScheme: require_document_color_scheme.readSlideSchemeColorSchemeAtom(colorSchemeRecord)
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return mastersById;
|
|
97
|
+
}
|
|
98
|
+
function readSlide(streamBytes, directory, persist, size, fontNames, notes, mastersById) {
|
|
64
99
|
const slideContainer = require_stream_persist.resolvePersistObject(streamBytes, directory, persist.persistIdRef, `SlidePersistAtom for slide ${persist.slideId}`);
|
|
65
100
|
if (slideContainer.header.recType !== 1006) throw new require_errors.PptFormatError(`persist object ${persist.persistIdRef} is record type 0x${slideContainer.header.recType.toString(16)}, not the RT_Slide (0x${require_record_types.RT_Slide.toString(16)}) its SlidePersistAtom promised`);
|
|
66
|
-
const
|
|
101
|
+
const slideChildren = require_record_tree.childRecords(slideContainer);
|
|
102
|
+
const slideAtomRecord = require_record_tree.findChild(slideChildren, require_record_types.RT_SlideAtom);
|
|
103
|
+
if (slideAtomRecord === void 0) throw new require_errors.PptFormatError(`SlideContainer for slide ${persist.slideId} has no SlideAtom, which [MS-PPT] 2.5.1 requires as its first child`);
|
|
104
|
+
const { masterIdRef } = require_document_master.readSlideAtom(slideAtomRecord);
|
|
105
|
+
const master = mastersById.get(masterIdRef);
|
|
106
|
+
if (master === void 0) throw new require_errors.PptFormatError(`slide ${persist.slideId}'s own SlideAtom names masterIdRef ${masterIdRef}, which the master list does not contain`);
|
|
107
|
+
const masterInfo = {
|
|
108
|
+
styles: master.styles,
|
|
109
|
+
colorScheme: colorSchemeFor(slideChildren, master)
|
|
110
|
+
};
|
|
111
|
+
const drawing = require_record_tree.findChild(slideChildren, require_record_types.RT_Drawing);
|
|
67
112
|
const shapes = [];
|
|
68
113
|
for (const shape of drawing === void 0 ? [] : require_drawing_shapes.readDrawingShapes(drawing)) {
|
|
69
114
|
if (shape.anchor === void 0) continue;
|
|
@@ -80,7 +125,7 @@ function readSlide(streamBytes, directory, persist, size, fontNames, notes) {
|
|
|
80
125
|
insetTopPt: DEFAULT_INSET_TOP_BOTTOM_PT,
|
|
81
126
|
insetRightPt: DEFAULT_INSET_LEFT_RIGHT_PT,
|
|
82
127
|
insetBottomPt: DEFAULT_INSET_TOP_BOTTOM_PT,
|
|
83
|
-
blocks: blocksFor(shape.clientTextbox, persist, fontNames)
|
|
128
|
+
blocks: blocksFor(shape.clientTextbox, persist, fontNames, masterInfo)
|
|
84
129
|
});
|
|
85
130
|
}
|
|
86
131
|
return {
|
|
@@ -89,11 +134,16 @@ function readSlide(streamBytes, directory, persist, size, fontNames, notes) {
|
|
|
89
134
|
notes
|
|
90
135
|
};
|
|
91
136
|
}
|
|
92
|
-
function readPptStreams(currentUserStream, powerPointDocumentStream) {
|
|
137
|
+
function readPptStreams(currentUserStream, powerPointDocumentStream, password) {
|
|
93
138
|
const currentUser = require_stream_current_user.readCurrentUserAtom(currentUserStream);
|
|
94
|
-
if (currentUser.encrypted) throw new require_errors.PptEncryptedError("the CurrentUserAtom's headerToken marks this document as encrypted, and this package does not implement [MS-PPT]'s encryption");
|
|
95
139
|
const { directory, currentEdit } = require_stream_persist.buildPersistDirectory(powerPointDocumentStream, currentUser.offsetToCurrentEdit);
|
|
96
|
-
|
|
140
|
+
let streamBytes = powerPointDocumentStream;
|
|
141
|
+
if (currentUser.encrypted) {
|
|
142
|
+
if (password === void 0) throw new require_errors.PptEncryptedError("the CurrentUserAtom's headerToken marks this document as RC4 CryptoAPI-encrypted ([MS-OFFCRYPTO] 2.3.5); call readPptStreams with a password to decrypt it");
|
|
143
|
+
if (currentEdit.encryptSessionPersistIdRef === void 0) throw new require_errors.PptFormatError("the CurrentUserAtom marks this document as encrypted, but its current UserEditAtom carries no encryptSessionPersistIdRef");
|
|
144
|
+
streamBytes = require_encryption.decryptPptDocumentStream(powerPointDocumentStream, directory, currentEdit.encryptSessionPersistIdRef, password);
|
|
145
|
+
}
|
|
146
|
+
const documentContainer = require_stream_persist.resolvePersistObject(streamBytes, directory, currentEdit.docPersistIdRef, "UserEditAtom.docPersistIdRef");
|
|
97
147
|
if (documentContainer.header.recType !== 1e3) throw new require_errors.PptFormatError(`the document persist object is record type 0x${documentContainer.header.recType.toString(16)}, not RT_Document (0x${require_record_types.RT_Document.toString(16)})`);
|
|
98
148
|
const children = require_record_tree.childRecords(documentContainer);
|
|
99
149
|
const documentAtomRecord = require_record_tree.findChild(children, require_record_types.RT_DocumentAtom);
|
|
@@ -105,18 +155,21 @@ function readPptStreams(currentUserStream, powerPointDocumentStream) {
|
|
|
105
155
|
};
|
|
106
156
|
const environment = require_record_tree.findChild(children, require_record_types.RT_Environment);
|
|
107
157
|
const fontNames = environment === void 0 ? [] : require_document_fonts.readFontNames(environment);
|
|
158
|
+
const documentDefaultRecord = environment === void 0 ? void 0 : require_record_tree.findChild(require_record_tree.childRecords(environment), require_record_types.RT_TextMasterStyleAtom);
|
|
159
|
+
const documentDefault = documentDefaultRecord === void 0 ? void 0 : require_text_style.readTextMasterStyleAtom(documentDefaultRecord);
|
|
108
160
|
const listWithInstance = (instance) => children.find((record) => record.header.recType === 4080 && record.header.recInstance === instance);
|
|
161
|
+
const mastersById = readMastersById(streamBytes, directory, listWithInstance(1), documentDefault);
|
|
109
162
|
const slideList = listWithInstance(0);
|
|
110
163
|
const persists = slideList === void 0 ? [] : require_document_slide_list.readSlideListWithText(slideList);
|
|
111
|
-
const notesBySlideId = readNotesBySlideId(
|
|
164
|
+
const notesBySlideId = readNotesBySlideId(streamBytes, directory, listWithInstance(2));
|
|
112
165
|
return {
|
|
113
166
|
metadata: {},
|
|
114
|
-
slides: persists.map((persist) => readSlide(
|
|
167
|
+
slides: persists.map((persist) => readSlide(streamBytes, directory, persist, size, fontNames, notesBySlideId.get(persist.slideId) ?? "", mastersById))
|
|
115
168
|
};
|
|
116
169
|
}
|
|
117
|
-
function readPptContent(bytes) {
|
|
170
|
+
function readPptContent(bytes, password) {
|
|
118
171
|
const streams = (0, archive_codec.readCompoundFile)(bytes);
|
|
119
|
-
const document = readPptStreams(requireStream(streams, CURRENT_USER_STREAM), requireStream(streams, POWERPOINT_DOCUMENT_STREAM));
|
|
172
|
+
const document = readPptStreams(requireStream(streams, CURRENT_USER_STREAM), requireStream(streams, POWERPOINT_DOCUMENT_STREAM), password);
|
|
120
173
|
const metadataStream = streams.find((stream) => stream.path === SUMMARY_INFORMATION_STREAM);
|
|
121
174
|
if (metadataStream === void 0) return document;
|
|
122
175
|
return {
|
|
@@ -124,8 +177,8 @@ function readPptContent(bytes) {
|
|
|
124
177
|
metadata: (0, archive_codec.summaryInformationToLayoutMetadata)((0, archive_codec.readSummaryInformation)(metadataStream.bytes))
|
|
125
178
|
};
|
|
126
179
|
}
|
|
127
|
-
function readPpt(bytes) {
|
|
128
|
-
const { metadata, slides } = readPptContent(bytes);
|
|
180
|
+
function readPpt(bytes, password) {
|
|
181
|
+
const { metadata, slides } = readPptContent(bytes, password);
|
|
129
182
|
const document = {
|
|
130
183
|
kind: "presentation",
|
|
131
184
|
metadata,
|
package/dist/read.d.cts
CHANGED
|
@@ -10,8 +10,8 @@ interface PptDocument {
|
|
|
10
10
|
readonly metadata: LayoutMetadata;
|
|
11
11
|
readonly slides: readonly ContentSlide[];
|
|
12
12
|
}
|
|
13
|
-
declare function readPptStreams(currentUserStream: Uint8Array<ArrayBuffer>, powerPointDocumentStream: Uint8Array<ArrayBuffer
|
|
14
|
-
declare function readPptContent(bytes: Uint8Array<ArrayBuffer
|
|
15
|
-
declare function readPpt(bytes: Uint8Array<ArrayBuffer
|
|
13
|
+
declare function readPptStreams(currentUserStream: Uint8Array<ArrayBuffer>, powerPointDocumentStream: Uint8Array<ArrayBuffer>, password?: string): PptDocument;
|
|
14
|
+
declare function readPptContent(bytes: Uint8Array<ArrayBuffer>, password?: string): PptDocument;
|
|
15
|
+
declare function readPpt(bytes: Uint8Array<ArrayBuffer>, password?: string): DocumentTree;
|
|
16
16
|
//#endregion
|
|
17
17
|
export { CURRENT_USER_STREAM, DEFAULT_INSET_LEFT_RIGHT_PT, DEFAULT_INSET_TOP_BOTTOM_PT, POWERPOINT_DOCUMENT_STREAM, PptDocument, SUMMARY_INFORMATION_STREAM, readPpt, readPptContent, readPptStreams };
|
package/dist/read.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ interface PptDocument {
|
|
|
10
10
|
readonly metadata: LayoutMetadata;
|
|
11
11
|
readonly slides: readonly ContentSlide[];
|
|
12
12
|
}
|
|
13
|
-
declare function readPptStreams(currentUserStream: Uint8Array<ArrayBuffer>, powerPointDocumentStream: Uint8Array<ArrayBuffer
|
|
14
|
-
declare function readPptContent(bytes: Uint8Array<ArrayBuffer
|
|
15
|
-
declare function readPpt(bytes: Uint8Array<ArrayBuffer
|
|
13
|
+
declare function readPptStreams(currentUserStream: Uint8Array<ArrayBuffer>, powerPointDocumentStream: Uint8Array<ArrayBuffer>, password?: string): PptDocument;
|
|
14
|
+
declare function readPptContent(bytes: Uint8Array<ArrayBuffer>, password?: string): PptDocument;
|
|
15
|
+
declare function readPpt(bytes: Uint8Array<ArrayBuffer>, password?: string): DocumentTree;
|
|
16
16
|
//#endregion
|
|
17
17
|
export { CURRENT_USER_STREAM, DEFAULT_INSET_LEFT_RIGHT_PT, DEFAULT_INSET_TOP_BOTTOM_PT, POWERPOINT_DOCUMENT_STREAM, PptDocument, SUMMARY_INFORMATION_STREAM, readPpt, readPptContent, readPptStreams };
|
package/dist/read.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { PptEncryptedError, PptFormatError } from "./errors.js";
|
|
2
2
|
import { childRecords, findChild } from "./record/tree.js";
|
|
3
|
-
import { RT_Document, RT_DocumentAtom, RT_Drawing, RT_Environment, RT_OutlineTextRefAtom, RT_Slide, RT_StyleTextPropAtom } from "./record/types.js";
|
|
4
|
-
import { readStyleTextPropAtom } from "./text/style.js";
|
|
5
|
-
import { characterCountOf, readTextBody } from "./text/atoms.js";
|
|
3
|
+
import { RT_ColorSchemeAtom, RT_Document, RT_DocumentAtom, RT_Drawing, RT_Environment, RT_MainMaster, RT_OutlineTextRefAtom, RT_Slide, RT_SlideAtom, RT_StyleTextPropAtom, RT_TextHeaderAtom, RT_TextMasterStyleAtom } from "./record/types.js";
|
|
4
|
+
import { readStyleTextPropAtom, readTextMasterStyleAtom } from "./text/style.js";
|
|
5
|
+
import { characterCountOf, readTextBody, readTextHeaderAtom } from "./text/atoms.js";
|
|
6
6
|
import { masterUnitsToPoints } from "./units.js";
|
|
7
|
+
import { readSlideSchemeColorSchemeAtom } from "./document/color-scheme.js";
|
|
8
|
+
import { buildMasterStyleTable, readSlideAtom } from "./document/master.js";
|
|
7
9
|
import { buildParagraphs } from "./content.js";
|
|
10
|
+
import { decryptPptDocumentStream } from "./encryption.js";
|
|
8
11
|
import { readDocumentAtom } from "./document/document-atom.js";
|
|
9
12
|
import { readFontNames } from "./document/fonts.js";
|
|
10
13
|
import { readNotesListWithText } from "./document/notes-list.js";
|
|
@@ -34,21 +37,31 @@ function requireStream(streams, name) {
|
|
|
34
37
|
function textRecordsFor(clientTextbox, persist) {
|
|
35
38
|
const children = childRecords(clientTextbox);
|
|
36
39
|
const outlineRef = findChild(children, RT_OutlineTextRefAtom);
|
|
37
|
-
if (outlineRef === void 0)
|
|
40
|
+
if (outlineRef === void 0) {
|
|
41
|
+
const headerRecord = findChild(children, RT_TextHeaderAtom);
|
|
42
|
+
if (headerRecord === void 0) throw new PptFormatError("a client textbox's own text records carry no TextHeaderAtom, which [MS-PPT] 2.9.1 requires to precede its TextCharsAtom/TextBytesAtom");
|
|
43
|
+
return {
|
|
44
|
+
textType: readTextHeaderAtom(headerRecord),
|
|
45
|
+
records: children
|
|
46
|
+
};
|
|
47
|
+
}
|
|
38
48
|
if (outlineRef.data.length < 4) throw new PptFormatError(`OutlineTextRefAtom at offset ${outlineRef.offset} carries ${outlineRef.data.length} bytes, fewer than the 4 its index field needs`);
|
|
39
49
|
const index = new DataView(outlineRef.data.buffer, outlineRef.data.byteOffset, outlineRef.data.byteLength).getInt32(0, true);
|
|
40
50
|
const outlineText = persist.texts[index];
|
|
41
51
|
if (outlineText === void 0) throw new PptFormatError(`OutlineTextRefAtom references text ${index} of slide ${persist.slideId}, which has only ${persist.texts.length} texts in the slide list`);
|
|
42
|
-
return
|
|
52
|
+
return {
|
|
53
|
+
textType: outlineText.textType,
|
|
54
|
+
records: outlineText.records
|
|
55
|
+
};
|
|
43
56
|
}
|
|
44
|
-
function blocksFor(clientTextbox, persist, fontNames) {
|
|
57
|
+
function blocksFor(clientTextbox, persist, fontNames, masterInfo) {
|
|
45
58
|
if (clientTextbox === void 0) return [];
|
|
46
|
-
const records = textRecordsFor(clientTextbox, persist);
|
|
59
|
+
const { textType, records } = textRecordsFor(clientTextbox, persist);
|
|
47
60
|
const text = readTextBody(records);
|
|
48
61
|
if (text === void 0) return [];
|
|
49
62
|
const styleRecord = findChild(records, RT_StyleTextPropAtom);
|
|
50
63
|
const style = styleRecord === void 0 ? NO_STYLE : readStyleTextPropAtom(styleRecord, characterCountOf(text));
|
|
51
|
-
return buildParagraphs(text, style, fontNames);
|
|
64
|
+
return buildParagraphs(text, style, fontNames, masterInfo.styles, textType, masterInfo.colorScheme);
|
|
52
65
|
}
|
|
53
66
|
function readNotesBySlideId(streamBytes, directory, notesList) {
|
|
54
67
|
const notes = /* @__PURE__ */ new Map();
|
|
@@ -59,10 +72,42 @@ function readNotesBySlideId(streamBytes, directory, notesList) {
|
|
|
59
72
|
}
|
|
60
73
|
return notes;
|
|
61
74
|
}
|
|
62
|
-
function
|
|
75
|
+
function colorSchemeFor(slideChildren, master) {
|
|
76
|
+
const ownScheme = findChild(slideChildren, RT_ColorSchemeAtom);
|
|
77
|
+
return ownScheme === void 0 ? master.colorScheme : readSlideSchemeColorSchemeAtom(ownScheme);
|
|
78
|
+
}
|
|
79
|
+
function readMastersById(streamBytes, directory, masterList, documentDefault) {
|
|
80
|
+
const mastersById = /* @__PURE__ */ new Map();
|
|
81
|
+
if (masterList === void 0) return mastersById;
|
|
82
|
+
for (const persist of readSlideListWithText(masterList)) {
|
|
83
|
+
const masterContainer = resolvePersistObject(streamBytes, directory, persist.persistIdRef, `MasterPersistAtom for master ${persist.slideId}`);
|
|
84
|
+
if (masterContainer.header.recType !== 1016) throw new PptFormatError(`persist object ${persist.persistIdRef} is record type 0x${masterContainer.header.recType.toString(16)}, not the RT_MainMaster (0x${RT_MainMaster.toString(16)}) its MasterPersistAtom promised`);
|
|
85
|
+
const masterChildren = childRecords(masterContainer);
|
|
86
|
+
const masterAtoms = masterChildren.filter((record) => record.header.recType === RT_TextMasterStyleAtom).map(readTextMasterStyleAtom);
|
|
87
|
+
const styles = buildMasterStyleTable(masterAtoms, documentDefault);
|
|
88
|
+
const colorSchemeRecord = findChild(masterChildren, RT_ColorSchemeAtom);
|
|
89
|
+
if (colorSchemeRecord === void 0) throw new PptFormatError(`MainMasterContainer for master ${persist.slideId} has no SlideSchemeColorSchemeAtom, which [MS-PPT] 2.5.3 requires`);
|
|
90
|
+
mastersById.set(persist.slideId, {
|
|
91
|
+
styles,
|
|
92
|
+
colorScheme: readSlideSchemeColorSchemeAtom(colorSchemeRecord)
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return mastersById;
|
|
96
|
+
}
|
|
97
|
+
function readSlide(streamBytes, directory, persist, size, fontNames, notes, mastersById) {
|
|
63
98
|
const slideContainer = resolvePersistObject(streamBytes, directory, persist.persistIdRef, `SlidePersistAtom for slide ${persist.slideId}`);
|
|
64
99
|
if (slideContainer.header.recType !== 1006) throw new PptFormatError(`persist object ${persist.persistIdRef} is record type 0x${slideContainer.header.recType.toString(16)}, not the RT_Slide (0x${RT_Slide.toString(16)}) its SlidePersistAtom promised`);
|
|
65
|
-
const
|
|
100
|
+
const slideChildren = childRecords(slideContainer);
|
|
101
|
+
const slideAtomRecord = findChild(slideChildren, RT_SlideAtom);
|
|
102
|
+
if (slideAtomRecord === void 0) throw new PptFormatError(`SlideContainer for slide ${persist.slideId} has no SlideAtom, which [MS-PPT] 2.5.1 requires as its first child`);
|
|
103
|
+
const { masterIdRef } = readSlideAtom(slideAtomRecord);
|
|
104
|
+
const master = mastersById.get(masterIdRef);
|
|
105
|
+
if (master === void 0) throw new PptFormatError(`slide ${persist.slideId}'s own SlideAtom names masterIdRef ${masterIdRef}, which the master list does not contain`);
|
|
106
|
+
const masterInfo = {
|
|
107
|
+
styles: master.styles,
|
|
108
|
+
colorScheme: colorSchemeFor(slideChildren, master)
|
|
109
|
+
};
|
|
110
|
+
const drawing = findChild(slideChildren, RT_Drawing);
|
|
66
111
|
const shapes = [];
|
|
67
112
|
for (const shape of drawing === void 0 ? [] : readDrawingShapes(drawing)) {
|
|
68
113
|
if (shape.anchor === void 0) continue;
|
|
@@ -79,7 +124,7 @@ function readSlide(streamBytes, directory, persist, size, fontNames, notes) {
|
|
|
79
124
|
insetTopPt: DEFAULT_INSET_TOP_BOTTOM_PT,
|
|
80
125
|
insetRightPt: DEFAULT_INSET_LEFT_RIGHT_PT,
|
|
81
126
|
insetBottomPt: DEFAULT_INSET_TOP_BOTTOM_PT,
|
|
82
|
-
blocks: blocksFor(shape.clientTextbox, persist, fontNames)
|
|
127
|
+
blocks: blocksFor(shape.clientTextbox, persist, fontNames, masterInfo)
|
|
83
128
|
});
|
|
84
129
|
}
|
|
85
130
|
return {
|
|
@@ -88,11 +133,16 @@ function readSlide(streamBytes, directory, persist, size, fontNames, notes) {
|
|
|
88
133
|
notes
|
|
89
134
|
};
|
|
90
135
|
}
|
|
91
|
-
function readPptStreams(currentUserStream, powerPointDocumentStream) {
|
|
136
|
+
function readPptStreams(currentUserStream, powerPointDocumentStream, password) {
|
|
92
137
|
const currentUser = readCurrentUserAtom(currentUserStream);
|
|
93
|
-
if (currentUser.encrypted) throw new PptEncryptedError("the CurrentUserAtom's headerToken marks this document as encrypted, and this package does not implement [MS-PPT]'s encryption");
|
|
94
138
|
const { directory, currentEdit } = buildPersistDirectory(powerPointDocumentStream, currentUser.offsetToCurrentEdit);
|
|
95
|
-
|
|
139
|
+
let streamBytes = powerPointDocumentStream;
|
|
140
|
+
if (currentUser.encrypted) {
|
|
141
|
+
if (password === void 0) throw new PptEncryptedError("the CurrentUserAtom's headerToken marks this document as RC4 CryptoAPI-encrypted ([MS-OFFCRYPTO] 2.3.5); call readPptStreams with a password to decrypt it");
|
|
142
|
+
if (currentEdit.encryptSessionPersistIdRef === void 0) throw new PptFormatError("the CurrentUserAtom marks this document as encrypted, but its current UserEditAtom carries no encryptSessionPersistIdRef");
|
|
143
|
+
streamBytes = decryptPptDocumentStream(powerPointDocumentStream, directory, currentEdit.encryptSessionPersistIdRef, password);
|
|
144
|
+
}
|
|
145
|
+
const documentContainer = resolvePersistObject(streamBytes, directory, currentEdit.docPersistIdRef, "UserEditAtom.docPersistIdRef");
|
|
96
146
|
if (documentContainer.header.recType !== 1e3) throw new PptFormatError(`the document persist object is record type 0x${documentContainer.header.recType.toString(16)}, not RT_Document (0x${RT_Document.toString(16)})`);
|
|
97
147
|
const children = childRecords(documentContainer);
|
|
98
148
|
const documentAtomRecord = findChild(children, RT_DocumentAtom);
|
|
@@ -104,18 +154,21 @@ function readPptStreams(currentUserStream, powerPointDocumentStream) {
|
|
|
104
154
|
};
|
|
105
155
|
const environment = findChild(children, RT_Environment);
|
|
106
156
|
const fontNames = environment === void 0 ? [] : readFontNames(environment);
|
|
157
|
+
const documentDefaultRecord = environment === void 0 ? void 0 : findChild(childRecords(environment), RT_TextMasterStyleAtom);
|
|
158
|
+
const documentDefault = documentDefaultRecord === void 0 ? void 0 : readTextMasterStyleAtom(documentDefaultRecord);
|
|
107
159
|
const listWithInstance = (instance) => children.find((record) => record.header.recType === 4080 && record.header.recInstance === instance);
|
|
160
|
+
const mastersById = readMastersById(streamBytes, directory, listWithInstance(1), documentDefault);
|
|
108
161
|
const slideList = listWithInstance(0);
|
|
109
162
|
const persists = slideList === void 0 ? [] : readSlideListWithText(slideList);
|
|
110
|
-
const notesBySlideId = readNotesBySlideId(
|
|
163
|
+
const notesBySlideId = readNotesBySlideId(streamBytes, directory, listWithInstance(2));
|
|
111
164
|
return {
|
|
112
165
|
metadata: {},
|
|
113
|
-
slides: persists.map((persist) => readSlide(
|
|
166
|
+
slides: persists.map((persist) => readSlide(streamBytes, directory, persist, size, fontNames, notesBySlideId.get(persist.slideId) ?? "", mastersById))
|
|
114
167
|
};
|
|
115
168
|
}
|
|
116
|
-
function readPptContent(bytes) {
|
|
169
|
+
function readPptContent(bytes, password) {
|
|
117
170
|
const streams = readCompoundFile(bytes);
|
|
118
|
-
const document = readPptStreams(requireStream(streams, CURRENT_USER_STREAM), requireStream(streams, POWERPOINT_DOCUMENT_STREAM));
|
|
171
|
+
const document = readPptStreams(requireStream(streams, CURRENT_USER_STREAM), requireStream(streams, POWERPOINT_DOCUMENT_STREAM), password);
|
|
119
172
|
const metadataStream = streams.find((stream) => stream.path === SUMMARY_INFORMATION_STREAM);
|
|
120
173
|
if (metadataStream === void 0) return document;
|
|
121
174
|
return {
|
|
@@ -123,8 +176,8 @@ function readPptContent(bytes) {
|
|
|
123
176
|
metadata: summaryInformationToLayoutMetadata(readSummaryInformation(metadataStream.bytes))
|
|
124
177
|
};
|
|
125
178
|
}
|
|
126
|
-
function readPpt(bytes) {
|
|
127
|
-
const { metadata, slides } = readPptContent(bytes);
|
|
179
|
+
function readPpt(bytes, password) {
|
|
180
|
+
const { metadata, slides } = readPptContent(bytes, password);
|
|
128
181
|
const document = {
|
|
129
182
|
kind: "presentation",
|
|
130
183
|
metadata,
|
|
@@ -4,12 +4,18 @@ const require_text_style = require("./style.cjs");
|
|
|
4
4
|
const require_record_write = require("../record/write.cjs");
|
|
5
5
|
//#region src/text/style-write.ts
|
|
6
6
|
function writeColorIndexStruct(color) {
|
|
7
|
-
return new Uint8Array([
|
|
8
|
-
color.red,
|
|
9
|
-
color.green,
|
|
10
|
-
color.blue,
|
|
7
|
+
if (color.kind === "rgb") return new Uint8Array([
|
|
8
|
+
color.rgb.red,
|
|
9
|
+
color.rgb.green,
|
|
10
|
+
color.rgb.blue,
|
|
11
11
|
254
|
|
12
12
|
]);
|
|
13
|
+
return new Uint8Array([
|
|
14
|
+
0,
|
|
15
|
+
0,
|
|
16
|
+
0,
|
|
17
|
+
color.schemeIndex
|
|
18
|
+
]);
|
|
13
19
|
}
|
|
14
20
|
function writeTextPFException(properties) {
|
|
15
21
|
let masks = 0;
|
package/dist/text/style-write.js
CHANGED
|
@@ -3,12 +3,18 @@ import { CF_COLOR, CF_SIZE, CF_TYPEFACE, PF_ALIGN, PF_INDENT, PF_LINE_SPACING, P
|
|
|
3
3
|
import { concatBytes, i16le, u16le, u32le, writeAtom } from "../record/write.js";
|
|
4
4
|
//#region src/text/style-write.ts
|
|
5
5
|
function writeColorIndexStruct(color) {
|
|
6
|
-
return new Uint8Array([
|
|
7
|
-
color.red,
|
|
8
|
-
color.green,
|
|
9
|
-
color.blue,
|
|
6
|
+
if (color.kind === "rgb") return new Uint8Array([
|
|
7
|
+
color.rgb.red,
|
|
8
|
+
color.rgb.green,
|
|
9
|
+
color.rgb.blue,
|
|
10
10
|
254
|
|
11
11
|
]);
|
|
12
|
+
return new Uint8Array([
|
|
13
|
+
0,
|
|
14
|
+
0,
|
|
15
|
+
0,
|
|
16
|
+
color.schemeIndex
|
|
17
|
+
]);
|
|
12
18
|
}
|
|
13
19
|
function writeTextPFException(properties) {
|
|
14
20
|
let masks = 0;
|
package/dist/text/style.cjs
CHANGED
|
@@ -51,6 +51,8 @@ const STYLE_UNDERLINE = 4;
|
|
|
51
51
|
const STYLE_SHADOW = 16;
|
|
52
52
|
const STYLE_EMBOSS = 512;
|
|
53
53
|
const COLOR_INDEX_SRGB = 254;
|
|
54
|
+
const COLOR_INDEX_UNDEFINED = 255;
|
|
55
|
+
const COLOR_SCHEME_SLOT_COUNT = 8;
|
|
54
56
|
var FieldCursor = class {
|
|
55
57
|
data;
|
|
56
58
|
describe;
|
|
@@ -91,11 +93,20 @@ var FieldCursor = class {
|
|
|
91
93
|
function readColorIndexStruct(cursor) {
|
|
92
94
|
const [red, green, blue, index] = cursor.bytes(4);
|
|
93
95
|
if (red === void 0 || green === void 0 || blue === void 0 || index === void 0) throw new require_errors.PptFormatError("ColorIndexStruct read returned fewer than its four bytes");
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
if (index === 254) return {
|
|
97
|
+
kind: "rgb",
|
|
98
|
+
rgb: {
|
|
99
|
+
red,
|
|
100
|
+
green,
|
|
101
|
+
blue
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
if (index === 255) return;
|
|
105
|
+
if (index < 8) return {
|
|
106
|
+
kind: "scheme",
|
|
107
|
+
schemeIndex: index
|
|
108
|
+
};
|
|
109
|
+
throw new require_errors.PptFormatError(`ColorIndexStruct index 0x${index.toString(16)} is none of a colour-scheme slot (0x00-0x07), the literal-colour sentinel (0x${254 .toString(16)}), or the undefined-colour sentinel (0x${255 .toString(16)})`);
|
|
99
110
|
}
|
|
100
111
|
function readTextPFException(cursor, indentLevel) {
|
|
101
112
|
const masks = cursor.u32();
|
|
@@ -175,6 +186,30 @@ function readStyleTextPropAtom(record, characterCount) {
|
|
|
175
186
|
characterRuns: readRuns(cursor, characterCount, "StyleTextPropAtom character runs", readTextCFException)
|
|
176
187
|
};
|
|
177
188
|
}
|
|
189
|
+
const MASTER_STYLE_MAX_LEVELS = 5;
|
|
190
|
+
const MASTER_STYLE_TYPES_WITH_EXPLICIT_LEVEL = 5;
|
|
191
|
+
function readTextMasterStyleAtom(record) {
|
|
192
|
+
if (record.header.recType !== 4003) throw new require_errors.PptFormatError(`expected RT_TextMasterStyleAtom (0x${require_record_types.RT_TextMasterStyleAtom.toString(16)}) at offset ${record.offset}, found record type 0x${record.header.recType.toString(16)}`);
|
|
193
|
+
const textType = record.header.recInstance;
|
|
194
|
+
const cursor = new FieldCursor(record.data, 0, "TextMasterStyleAtom");
|
|
195
|
+
const cLevels = cursor.u16();
|
|
196
|
+
if (cLevels > MASTER_STYLE_MAX_LEVELS) throw new require_errors.PptFormatError(`TextMasterStyleAtom at offset ${record.offset} declares cLevels ${cLevels}, more than the mandated maximum of ${MASTER_STYLE_MAX_LEVELS}`);
|
|
197
|
+
const hasExplicitLevel = textType >= MASTER_STYLE_TYPES_WITH_EXPLICIT_LEVEL;
|
|
198
|
+
const levels = [];
|
|
199
|
+
for (let i = 0; i < cLevels; i += 1) {
|
|
200
|
+
if (hasExplicitLevel) cursor.u16();
|
|
201
|
+
const paragraph = readTextPFException(cursor, i);
|
|
202
|
+
const character = readTextCFException(cursor);
|
|
203
|
+
levels.push({
|
|
204
|
+
paragraph,
|
|
205
|
+
character
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
textType,
|
|
210
|
+
levels
|
|
211
|
+
};
|
|
212
|
+
}
|
|
178
213
|
//#endregion
|
|
179
214
|
exports.ALIGN_CENTER = ALIGN_CENTER;
|
|
180
215
|
exports.ALIGN_DISTRIBUTED = ALIGN_DISTRIBUTED;
|
|
@@ -199,6 +234,8 @@ exports.CF_SYMBOL_TYPEFACE = CF_SYMBOL_TYPEFACE;
|
|
|
199
234
|
exports.CF_TYPEFACE = CF_TYPEFACE;
|
|
200
235
|
exports.CF_UNDERLINE = CF_UNDERLINE;
|
|
201
236
|
exports.COLOR_INDEX_SRGB = COLOR_INDEX_SRGB;
|
|
237
|
+
exports.COLOR_INDEX_UNDEFINED = COLOR_INDEX_UNDEFINED;
|
|
238
|
+
exports.COLOR_SCHEME_SLOT_COUNT = COLOR_SCHEME_SLOT_COUNT;
|
|
202
239
|
exports.PF_ALIGN = PF_ALIGN;
|
|
203
240
|
exports.PF_BULLET_CHAR = PF_BULLET_CHAR;
|
|
204
241
|
exports.PF_BULLET_COLOR = PF_BULLET_COLOR;
|
|
@@ -226,3 +263,4 @@ exports.STYLE_ITALIC = STYLE_ITALIC;
|
|
|
226
263
|
exports.STYLE_SHADOW = STYLE_SHADOW;
|
|
227
264
|
exports.STYLE_UNDERLINE = STYLE_UNDERLINE;
|
|
228
265
|
exports.readStyleTextPropAtom = readStyleTextPropAtom;
|
|
266
|
+
exports.readTextMasterStyleAtom = readTextMasterStyleAtom;
|
package/dist/text/style.d.cts
CHANGED
|
@@ -49,11 +49,20 @@ declare const STYLE_UNDERLINE: number;
|
|
|
49
49
|
declare const STYLE_SHADOW: number;
|
|
50
50
|
declare const STYLE_EMBOSS: number;
|
|
51
51
|
declare const COLOR_INDEX_SRGB = 254;
|
|
52
|
+
declare const COLOR_INDEX_UNDEFINED = 255;
|
|
53
|
+
declare const COLOR_SCHEME_SLOT_COUNT = 8;
|
|
52
54
|
interface RgbColor {
|
|
53
55
|
readonly red: number;
|
|
54
56
|
readonly green: number;
|
|
55
57
|
readonly blue: number;
|
|
56
58
|
}
|
|
59
|
+
type RunColor = {
|
|
60
|
+
readonly kind: "rgb";
|
|
61
|
+
readonly rgb: RgbColor;
|
|
62
|
+
} | {
|
|
63
|
+
readonly kind: "scheme";
|
|
64
|
+
readonly schemeIndex: number;
|
|
65
|
+
};
|
|
57
66
|
interface ParagraphProperties {
|
|
58
67
|
readonly indentLevel: number;
|
|
59
68
|
readonly alignment: number | undefined;
|
|
@@ -73,7 +82,7 @@ interface CharacterProperties {
|
|
|
73
82
|
readonly emboss: boolean | undefined;
|
|
74
83
|
readonly fontRef: number | undefined;
|
|
75
84
|
readonly sizePt: number | undefined;
|
|
76
|
-
readonly color:
|
|
85
|
+
readonly color: RunColor | undefined;
|
|
77
86
|
}
|
|
78
87
|
interface StyleRun<T> {
|
|
79
88
|
readonly count: number;
|
|
@@ -84,5 +93,14 @@ interface StyleTextProps {
|
|
|
84
93
|
readonly characterRuns: readonly StyleRun<CharacterProperties>[];
|
|
85
94
|
}
|
|
86
95
|
declare function readStyleTextPropAtom(record: PptRecord, characterCount: number): StyleTextProps;
|
|
96
|
+
interface MasterStyleLevel {
|
|
97
|
+
readonly paragraph: ParagraphProperties;
|
|
98
|
+
readonly character: CharacterProperties;
|
|
99
|
+
}
|
|
100
|
+
interface MasterTextStyleAtom {
|
|
101
|
+
readonly textType: number;
|
|
102
|
+
readonly levels: readonly MasterStyleLevel[];
|
|
103
|
+
}
|
|
104
|
+
declare function readTextMasterStyleAtom(record: PptRecord): MasterTextStyleAtom;
|
|
87
105
|
//#endregion
|
|
88
|
-
export { ALIGN_CENTER, ALIGN_DISTRIBUTED, ALIGN_JUSTIFY, ALIGN_JUSTIFY_LOW, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_THAI_DISTRIBUTED, CF_ANSI_TYPEFACE, CF_BOLD, CF_COLOR, CF_EMBOSS, CF_FEHINT, CF_HAS_STYLE, CF_ITALIC, CF_KUMI, CF_OLD_EA_TYPEFACE, CF_POSITION, CF_SHADOW, CF_SIZE, CF_SYMBOL_TYPEFACE, CF_TYPEFACE, CF_UNDERLINE, COLOR_INDEX_SRGB, CharacterProperties, PF_ALIGN, PF_BULLET_CHAR, PF_BULLET_COLOR, PF_BULLET_FONT, PF_BULLET_HAS_COLOR, PF_BULLET_HAS_FONT, PF_BULLET_HAS_SIZE, PF_BULLET_SIZE, PF_CHAR_WRAP, PF_DEFAULT_TAB_SIZE, PF_FONT_ALIGN, PF_HAS_BULLET, PF_INDENT, PF_LEFT_MARGIN, PF_LINE_SPACING, PF_OVERFLOW, PF_SPACE_AFTER, PF_SPACE_BEFORE, PF_TAB_STOPS, PF_TEXT_DIRECTION, PF_WORD_WRAP, ParagraphProperties, RgbColor, STYLE_BOLD, STYLE_EMBOSS, STYLE_ITALIC, STYLE_SHADOW, STYLE_UNDERLINE, StyleRun, StyleTextProps, readStyleTextPropAtom };
|
|
106
|
+
export { ALIGN_CENTER, ALIGN_DISTRIBUTED, ALIGN_JUSTIFY, ALIGN_JUSTIFY_LOW, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_THAI_DISTRIBUTED, CF_ANSI_TYPEFACE, CF_BOLD, CF_COLOR, CF_EMBOSS, CF_FEHINT, CF_HAS_STYLE, CF_ITALIC, CF_KUMI, CF_OLD_EA_TYPEFACE, CF_POSITION, CF_SHADOW, CF_SIZE, CF_SYMBOL_TYPEFACE, CF_TYPEFACE, CF_UNDERLINE, COLOR_INDEX_SRGB, COLOR_INDEX_UNDEFINED, COLOR_SCHEME_SLOT_COUNT, CharacterProperties, MasterStyleLevel, MasterTextStyleAtom, PF_ALIGN, PF_BULLET_CHAR, PF_BULLET_COLOR, PF_BULLET_FONT, PF_BULLET_HAS_COLOR, PF_BULLET_HAS_FONT, PF_BULLET_HAS_SIZE, PF_BULLET_SIZE, PF_CHAR_WRAP, PF_DEFAULT_TAB_SIZE, PF_FONT_ALIGN, PF_HAS_BULLET, PF_INDENT, PF_LEFT_MARGIN, PF_LINE_SPACING, PF_OVERFLOW, PF_SPACE_AFTER, PF_SPACE_BEFORE, PF_TAB_STOPS, PF_TEXT_DIRECTION, PF_WORD_WRAP, ParagraphProperties, RgbColor, RunColor, STYLE_BOLD, STYLE_EMBOSS, STYLE_ITALIC, STYLE_SHADOW, STYLE_UNDERLINE, StyleRun, StyleTextProps, readStyleTextPropAtom, readTextMasterStyleAtom };
|
package/dist/text/style.d.ts
CHANGED
|
@@ -49,11 +49,20 @@ declare const STYLE_UNDERLINE: number;
|
|
|
49
49
|
declare const STYLE_SHADOW: number;
|
|
50
50
|
declare const STYLE_EMBOSS: number;
|
|
51
51
|
declare const COLOR_INDEX_SRGB = 254;
|
|
52
|
+
declare const COLOR_INDEX_UNDEFINED = 255;
|
|
53
|
+
declare const COLOR_SCHEME_SLOT_COUNT = 8;
|
|
52
54
|
interface RgbColor {
|
|
53
55
|
readonly red: number;
|
|
54
56
|
readonly green: number;
|
|
55
57
|
readonly blue: number;
|
|
56
58
|
}
|
|
59
|
+
type RunColor = {
|
|
60
|
+
readonly kind: "rgb";
|
|
61
|
+
readonly rgb: RgbColor;
|
|
62
|
+
} | {
|
|
63
|
+
readonly kind: "scheme";
|
|
64
|
+
readonly schemeIndex: number;
|
|
65
|
+
};
|
|
57
66
|
interface ParagraphProperties {
|
|
58
67
|
readonly indentLevel: number;
|
|
59
68
|
readonly alignment: number | undefined;
|
|
@@ -73,7 +82,7 @@ interface CharacterProperties {
|
|
|
73
82
|
readonly emboss: boolean | undefined;
|
|
74
83
|
readonly fontRef: number | undefined;
|
|
75
84
|
readonly sizePt: number | undefined;
|
|
76
|
-
readonly color:
|
|
85
|
+
readonly color: RunColor | undefined;
|
|
77
86
|
}
|
|
78
87
|
interface StyleRun<T> {
|
|
79
88
|
readonly count: number;
|
|
@@ -84,5 +93,14 @@ interface StyleTextProps {
|
|
|
84
93
|
readonly characterRuns: readonly StyleRun<CharacterProperties>[];
|
|
85
94
|
}
|
|
86
95
|
declare function readStyleTextPropAtom(record: PptRecord, characterCount: number): StyleTextProps;
|
|
96
|
+
interface MasterStyleLevel {
|
|
97
|
+
readonly paragraph: ParagraphProperties;
|
|
98
|
+
readonly character: CharacterProperties;
|
|
99
|
+
}
|
|
100
|
+
interface MasterTextStyleAtom {
|
|
101
|
+
readonly textType: number;
|
|
102
|
+
readonly levels: readonly MasterStyleLevel[];
|
|
103
|
+
}
|
|
104
|
+
declare function readTextMasterStyleAtom(record: PptRecord): MasterTextStyleAtom;
|
|
87
105
|
//#endregion
|
|
88
|
-
export { ALIGN_CENTER, ALIGN_DISTRIBUTED, ALIGN_JUSTIFY, ALIGN_JUSTIFY_LOW, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_THAI_DISTRIBUTED, CF_ANSI_TYPEFACE, CF_BOLD, CF_COLOR, CF_EMBOSS, CF_FEHINT, CF_HAS_STYLE, CF_ITALIC, CF_KUMI, CF_OLD_EA_TYPEFACE, CF_POSITION, CF_SHADOW, CF_SIZE, CF_SYMBOL_TYPEFACE, CF_TYPEFACE, CF_UNDERLINE, COLOR_INDEX_SRGB, CharacterProperties, PF_ALIGN, PF_BULLET_CHAR, PF_BULLET_COLOR, PF_BULLET_FONT, PF_BULLET_HAS_COLOR, PF_BULLET_HAS_FONT, PF_BULLET_HAS_SIZE, PF_BULLET_SIZE, PF_CHAR_WRAP, PF_DEFAULT_TAB_SIZE, PF_FONT_ALIGN, PF_HAS_BULLET, PF_INDENT, PF_LEFT_MARGIN, PF_LINE_SPACING, PF_OVERFLOW, PF_SPACE_AFTER, PF_SPACE_BEFORE, PF_TAB_STOPS, PF_TEXT_DIRECTION, PF_WORD_WRAP, ParagraphProperties, RgbColor, STYLE_BOLD, STYLE_EMBOSS, STYLE_ITALIC, STYLE_SHADOW, STYLE_UNDERLINE, StyleRun, StyleTextProps, readStyleTextPropAtom };
|
|
106
|
+
export { ALIGN_CENTER, ALIGN_DISTRIBUTED, ALIGN_JUSTIFY, ALIGN_JUSTIFY_LOW, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_THAI_DISTRIBUTED, CF_ANSI_TYPEFACE, CF_BOLD, CF_COLOR, CF_EMBOSS, CF_FEHINT, CF_HAS_STYLE, CF_ITALIC, CF_KUMI, CF_OLD_EA_TYPEFACE, CF_POSITION, CF_SHADOW, CF_SIZE, CF_SYMBOL_TYPEFACE, CF_TYPEFACE, CF_UNDERLINE, COLOR_INDEX_SRGB, COLOR_INDEX_UNDEFINED, COLOR_SCHEME_SLOT_COUNT, CharacterProperties, MasterStyleLevel, MasterTextStyleAtom, PF_ALIGN, PF_BULLET_CHAR, PF_BULLET_COLOR, PF_BULLET_FONT, PF_BULLET_HAS_COLOR, PF_BULLET_HAS_FONT, PF_BULLET_HAS_SIZE, PF_BULLET_SIZE, PF_CHAR_WRAP, PF_DEFAULT_TAB_SIZE, PF_FONT_ALIGN, PF_HAS_BULLET, PF_INDENT, PF_LEFT_MARGIN, PF_LINE_SPACING, PF_OVERFLOW, PF_SPACE_AFTER, PF_SPACE_BEFORE, PF_TAB_STOPS, PF_TEXT_DIRECTION, PF_WORD_WRAP, ParagraphProperties, RgbColor, RunColor, STYLE_BOLD, STYLE_EMBOSS, STYLE_ITALIC, STYLE_SHADOW, STYLE_UNDERLINE, StyleRun, StyleTextProps, readStyleTextPropAtom, readTextMasterStyleAtom };
|
package/dist/text/style.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PptFormatError } from "../errors.js";
|
|
2
|
-
import { RT_StyleTextPropAtom } from "../record/types.js";
|
|
2
|
+
import { RT_StyleTextPropAtom, RT_TextMasterStyleAtom } from "../record/types.js";
|
|
3
3
|
//#region src/text/style.ts
|
|
4
4
|
const ALIGN_LEFT = 0;
|
|
5
5
|
const ALIGN_CENTER = 1;
|
|
@@ -50,6 +50,8 @@ const STYLE_UNDERLINE = 4;
|
|
|
50
50
|
const STYLE_SHADOW = 16;
|
|
51
51
|
const STYLE_EMBOSS = 512;
|
|
52
52
|
const COLOR_INDEX_SRGB = 254;
|
|
53
|
+
const COLOR_INDEX_UNDEFINED = 255;
|
|
54
|
+
const COLOR_SCHEME_SLOT_COUNT = 8;
|
|
53
55
|
var FieldCursor = class {
|
|
54
56
|
data;
|
|
55
57
|
describe;
|
|
@@ -90,11 +92,20 @@ var FieldCursor = class {
|
|
|
90
92
|
function readColorIndexStruct(cursor) {
|
|
91
93
|
const [red, green, blue, index] = cursor.bytes(4);
|
|
92
94
|
if (red === void 0 || green === void 0 || blue === void 0 || index === void 0) throw new PptFormatError("ColorIndexStruct read returned fewer than its four bytes");
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
if (index === 254) return {
|
|
96
|
+
kind: "rgb",
|
|
97
|
+
rgb: {
|
|
98
|
+
red,
|
|
99
|
+
green,
|
|
100
|
+
blue
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
if (index === 255) return;
|
|
104
|
+
if (index < 8) return {
|
|
105
|
+
kind: "scheme",
|
|
106
|
+
schemeIndex: index
|
|
107
|
+
};
|
|
108
|
+
throw new PptFormatError(`ColorIndexStruct index 0x${index.toString(16)} is none of a colour-scheme slot (0x00-0x07), the literal-colour sentinel (0x${254 .toString(16)}), or the undefined-colour sentinel (0x${255 .toString(16)})`);
|
|
98
109
|
}
|
|
99
110
|
function readTextPFException(cursor, indentLevel) {
|
|
100
111
|
const masks = cursor.u32();
|
|
@@ -174,5 +185,29 @@ function readStyleTextPropAtom(record, characterCount) {
|
|
|
174
185
|
characterRuns: readRuns(cursor, characterCount, "StyleTextPropAtom character runs", readTextCFException)
|
|
175
186
|
};
|
|
176
187
|
}
|
|
188
|
+
const MASTER_STYLE_MAX_LEVELS = 5;
|
|
189
|
+
const MASTER_STYLE_TYPES_WITH_EXPLICIT_LEVEL = 5;
|
|
190
|
+
function readTextMasterStyleAtom(record) {
|
|
191
|
+
if (record.header.recType !== 4003) throw new PptFormatError(`expected RT_TextMasterStyleAtom (0x${RT_TextMasterStyleAtom.toString(16)}) at offset ${record.offset}, found record type 0x${record.header.recType.toString(16)}`);
|
|
192
|
+
const textType = record.header.recInstance;
|
|
193
|
+
const cursor = new FieldCursor(record.data, 0, "TextMasterStyleAtom");
|
|
194
|
+
const cLevels = cursor.u16();
|
|
195
|
+
if (cLevels > MASTER_STYLE_MAX_LEVELS) throw new PptFormatError(`TextMasterStyleAtom at offset ${record.offset} declares cLevels ${cLevels}, more than the mandated maximum of ${MASTER_STYLE_MAX_LEVELS}`);
|
|
196
|
+
const hasExplicitLevel = textType >= MASTER_STYLE_TYPES_WITH_EXPLICIT_LEVEL;
|
|
197
|
+
const levels = [];
|
|
198
|
+
for (let i = 0; i < cLevels; i += 1) {
|
|
199
|
+
if (hasExplicitLevel) cursor.u16();
|
|
200
|
+
const paragraph = readTextPFException(cursor, i);
|
|
201
|
+
const character = readTextCFException(cursor);
|
|
202
|
+
levels.push({
|
|
203
|
+
paragraph,
|
|
204
|
+
character
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
textType,
|
|
209
|
+
levels
|
|
210
|
+
};
|
|
211
|
+
}
|
|
177
212
|
//#endregion
|
|
178
|
-
export { ALIGN_CENTER, ALIGN_DISTRIBUTED, ALIGN_JUSTIFY, ALIGN_JUSTIFY_LOW, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_THAI_DISTRIBUTED, CF_ANSI_TYPEFACE, CF_BOLD, CF_COLOR, CF_EMBOSS, CF_FEHINT, CF_HAS_STYLE, CF_ITALIC, CF_KUMI, CF_OLD_EA_TYPEFACE, CF_POSITION, CF_SHADOW, CF_SIZE, CF_SYMBOL_TYPEFACE, CF_TYPEFACE, CF_UNDERLINE, COLOR_INDEX_SRGB, PF_ALIGN, PF_BULLET_CHAR, PF_BULLET_COLOR, PF_BULLET_FONT, PF_BULLET_HAS_COLOR, PF_BULLET_HAS_FONT, PF_BULLET_HAS_SIZE, PF_BULLET_SIZE, PF_CHAR_WRAP, PF_DEFAULT_TAB_SIZE, PF_FONT_ALIGN, PF_HAS_BULLET, PF_INDENT, PF_LEFT_MARGIN, PF_LINE_SPACING, PF_OVERFLOW, PF_SPACE_AFTER, PF_SPACE_BEFORE, PF_TAB_STOPS, PF_TEXT_DIRECTION, PF_WORD_WRAP, STYLE_BOLD, STYLE_EMBOSS, STYLE_ITALIC, STYLE_SHADOW, STYLE_UNDERLINE, readStyleTextPropAtom };
|
|
213
|
+
export { ALIGN_CENTER, ALIGN_DISTRIBUTED, ALIGN_JUSTIFY, ALIGN_JUSTIFY_LOW, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_THAI_DISTRIBUTED, CF_ANSI_TYPEFACE, CF_BOLD, CF_COLOR, CF_EMBOSS, CF_FEHINT, CF_HAS_STYLE, CF_ITALIC, CF_KUMI, CF_OLD_EA_TYPEFACE, CF_POSITION, CF_SHADOW, CF_SIZE, CF_SYMBOL_TYPEFACE, CF_TYPEFACE, CF_UNDERLINE, COLOR_INDEX_SRGB, COLOR_INDEX_UNDEFINED, COLOR_SCHEME_SLOT_COUNT, PF_ALIGN, PF_BULLET_CHAR, PF_BULLET_COLOR, PF_BULLET_FONT, PF_BULLET_HAS_COLOR, PF_BULLET_HAS_FONT, PF_BULLET_HAS_SIZE, PF_BULLET_SIZE, PF_CHAR_WRAP, PF_DEFAULT_TAB_SIZE, PF_FONT_ALIGN, PF_HAS_BULLET, PF_INDENT, PF_LEFT_MARGIN, PF_LINE_SPACING, PF_OVERFLOW, PF_SPACE_AFTER, PF_SPACE_BEFORE, PF_TAB_STOPS, PF_TEXT_DIRECTION, PF_WORD_WRAP, STYLE_BOLD, STYLE_EMBOSS, STYLE_ITALIC, STYLE_SHADOW, STYLE_UNDERLINE, readStyleTextPropAtom, readTextMasterStyleAtom };
|