reamkit 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/core/converter/ream.d.ts +16 -0
- package/dist/esm/core/converter/ream.js +59 -9
- package/dist/esm/core/document-model/types.d.ts +18 -0
- package/dist/esm/core/drawingml/chart-geometry.js +11 -5
- package/dist/esm/core/drawingml/colors.d.ts +4 -2
- package/dist/esm/core/drawingml/colors.js +15 -0
- package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
- package/dist/esm/core/drawingml/theme-parser.js +64 -1
- package/dist/esm/core/fonts/families.d.ts +10 -0
- package/dist/esm/core/fonts/families.js +44 -0
- package/dist/esm/core/fonts/index.d.ts +3 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
- package/dist/esm/core/fonts/remote-fonts.js +114 -8
- package/dist/esm/core/fonts/scripts.d.ts +26 -0
- package/dist/esm/core/fonts/scripts.js +177 -0
- package/dist/esm/core/metafile/blit.d.ts +33 -0
- package/dist/esm/core/metafile/blit.js +67 -0
- package/dist/esm/core/metafile/dib.d.ts +61 -0
- package/dist/esm/core/metafile/dib.js +205 -0
- package/dist/esm/core/metafile/emf.js +137 -23
- package/dist/esm/core/metafile/picture.d.ts +12 -1
- package/dist/esm/core/metafile/wmf.js +149 -9
- package/dist/esm/core/ole/escher-blip.d.ts +12 -0
- package/dist/esm/core/ole/escher-blip.js +88 -0
- package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
- package/dist/esm/excel/print-model.js +3 -1
- package/dist/esm/excel/styles-parser.js +1 -1
- package/dist/esm/excel/xls/biff-reader.js +53 -18
- package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
- package/dist/esm/excel/xls/biff-styles.js +9 -7
- package/dist/esm/excel/xls/escher.js +90 -24
- package/dist/esm/layout/page-doc.d.ts +39 -0
- package/dist/esm/layout/styled-layout.d.ts +2 -2
- package/dist/esm/layout/styled-layout.js +301 -35
- package/dist/esm/pdf/styled-page-emitter.js +35 -2
- package/dist/esm/pdf-reader/image-decode.js +1 -1
- package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
- package/dist/esm/pptx/embedded-fonts.js +104 -0
- package/dist/esm/pptx/placeholder-cascade.d.ts +73 -6
- package/dist/esm/pptx/placeholder-cascade.js +114 -18
- package/dist/esm/pptx/ppt/ppt-reader.js +120 -10
- package/dist/esm/pptx/ppt/ppt-text.d.ts +66 -1
- package/dist/esm/pptx/ppt/ppt-text.js +576 -137
- package/dist/esm/pptx/pptx-reader.d.ts +8 -0
- package/dist/esm/pptx/pptx-reader.js +27 -5
- package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
- package/dist/esm/pptx/preset-table-styles.js +27 -0
- package/dist/esm/pptx/slide-parser.d.ts +7 -1
- package/dist/esm/pptx/slide-parser.js +106 -33
- package/dist/esm/pptx/sp-helpers.d.ts +2 -1
- package/dist/esm/pptx/sp-helpers.js +3 -2
- package/dist/esm/pptx/table-style.d.ts +9 -1
- package/dist/esm/pptx/table-style.js +49 -7
- package/dist/esm/word/document-parser.d.ts +7 -1
- package/dist/esm/word/document-parser.js +6 -6
- package/dist/esm/word/docx-reader.js +6 -3
- package/dist/esm/word/docx-to-pdf.d.ts +8 -7
- package/dist/esm/word/docx-to-pdf.js +25 -7
- package/dist/esm/word/drawing-parser.js +31 -19
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +6 -6
- package/dist/esm/word/paragraph-properties.d.ts +2 -1
- package/dist/esm/word/paragraph-properties.js +2 -2
- package/dist/esm/word/run-properties.d.ts +5 -2
- package/dist/esm/word/run-properties.js +13 -8
- package/dist/esm/word/styles-parser.d.ts +2 -1
- package/dist/esm/word/styles-parser.js +12 -12
- package/dist/esm/word/table-parser.js +3 -3
- package/dist/esm/word/theme-fonts.d.ts +10 -0
- package/dist/esm/word/theme-fonts.js +28 -0
- package/package.json +1 -1
- /package/dist/esm/{pdf-reader → core}/png-encode.d.ts +0 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { fromSymbolFont } from "../../core/metafile/symbol-fonts.js";
|
|
1
2
|
import { isCfb, openCfb } from "../../core/ole/cfb.js";
|
|
3
|
+
import { readEscherBlip } from "../../core/ole/escher-blip.js";
|
|
2
4
|
//#region src/pptx/ppt/ppt-text.ts
|
|
3
5
|
var RT_DOCUMENT = 1e3;
|
|
4
6
|
var RT_DOCUMENT_ATOM = 1001;
|
|
@@ -12,8 +14,12 @@ var RT_TEXT_HEADER_ATOM = 3999;
|
|
|
12
14
|
var RT_TEXT_CHARS_ATOM = 4e3;
|
|
13
15
|
var RT_STYLE_TEXT_PROP_ATOM = 4001;
|
|
14
16
|
var RT_TEXT_BYTES_ATOM = 4008;
|
|
17
|
+
var RT_OUTLINE_TEXT_REF_ATOM = 3998;
|
|
18
|
+
var RT_TEXT_MASTER_STYLE_ATOM = 4003;
|
|
15
19
|
var RT_SLIDE_ATOM = 1007;
|
|
16
20
|
var RT_MAIN_MASTER = 1016;
|
|
21
|
+
var RT_FONT_COLLECTION = 2005;
|
|
22
|
+
var RT_FONT_ENTITY_ATOM = 4023;
|
|
17
23
|
var RT_COLOR_SCHEME_ATOM = 2032;
|
|
18
24
|
var FBT_BSTORE_CONTAINER = 61441;
|
|
19
25
|
var FBT_BSE = 61447;
|
|
@@ -22,9 +28,28 @@ var FBT_FSP = 61450;
|
|
|
22
28
|
var FBT_OPT = 61451;
|
|
23
29
|
var FBT_CLIENT_TEXTBOX = 61453;
|
|
24
30
|
var FBT_CLIENT_ANCHOR = 61456;
|
|
31
|
+
var FBT_CLIENT_DATA = 61457;
|
|
32
|
+
var FBT_SPGR_CONTAINER = 61443;
|
|
33
|
+
var FBT_SPGR = 61449;
|
|
34
|
+
var FBT_CHILD_ANCHOR = 61455;
|
|
35
|
+
var RT_PLACEHOLDER_ATOM = 3011;
|
|
25
36
|
var PROP_PIB = 260;
|
|
37
|
+
var PROP_FILL_TYPE = 384;
|
|
26
38
|
var PROP_FILL_COLOR = 385;
|
|
39
|
+
var PROP_FILL_BACK_COLOR = 387;
|
|
40
|
+
var PROP_FILL_ANGLE = 395;
|
|
41
|
+
var PROP_FILL_BLIP = 390;
|
|
42
|
+
var PROP_GTEXT_UNICODE = 192;
|
|
43
|
+
var PROP_GTEXT_SIZE = 195;
|
|
44
|
+
var PROP_GTEXT_FONT = 197;
|
|
45
|
+
var PROP_FILL_WIDTH = 393;
|
|
46
|
+
var PROP_FILL_HEIGHT = 394;
|
|
47
|
+
var EMU_PER_POINT = 12700;
|
|
27
48
|
var PROP_LINE_COLOR = 448;
|
|
49
|
+
var PROP_FILL_BOOLS = 447;
|
|
50
|
+
var PROP_LINE_BOOLS = 511;
|
|
51
|
+
var FILL_F_FILLED = 16;
|
|
52
|
+
var LINE_F_LINE = 8;
|
|
28
53
|
var PROP_GEO_LEFT = 320;
|
|
29
54
|
var PROP_GEO_TOP = 321;
|
|
30
55
|
var PROP_GEO_RIGHT = 322;
|
|
@@ -37,8 +62,10 @@ var COLORREF_SCHEME_INDEX = 8;
|
|
|
37
62
|
var COLORREF_SYS_INDEX = 16;
|
|
38
63
|
var FBSE_FODELAY_OFFSET = 28;
|
|
39
64
|
var FSP_FLAG_PATRIARCH = 4;
|
|
65
|
+
var FSP_FLAG_BACKGROUND = 1024;
|
|
40
66
|
var TOKEN_ENCRYPTED = 4090610911;
|
|
41
67
|
var SLWT_INSTANCE_SLIDES = 0;
|
|
68
|
+
var SLWT_INSTANCE_MASTERS = 1;
|
|
42
69
|
var MAX_EDITS = 4096;
|
|
43
70
|
var MAX_DEPTH = 24;
|
|
44
71
|
function recordAt(stream, off) {
|
|
@@ -127,19 +154,19 @@ function extractPptContent(bytes) {
|
|
|
127
154
|
};
|
|
128
155
|
}
|
|
129
156
|
function slideHasContent(s) {
|
|
130
|
-
return s.shapes.some((sh) => shapeHasText(sh) || sh.image !== void 0 || sh.autoShape !== void 0);
|
|
157
|
+
return s.background !== void 0 || s.shapes.some((sh) => shapeHasText(sh) || sh.image !== void 0 || sh.autoShape !== void 0);
|
|
131
158
|
}
|
|
132
159
|
function shapeHasText(sh) {
|
|
133
160
|
return sh.paragraphs?.some((p) => paragraphText(p).length > 0) ?? false;
|
|
134
161
|
}
|
|
135
|
-
function slideShapes(slideData, img, outline,
|
|
136
|
-
const
|
|
137
|
-
if (!shapes.some(shapeHasText)) {
|
|
138
|
-
const inline = collectParagraphs(slideData, 0);
|
|
139
|
-
const text = inline.some((p) => paragraphText(p).length > 0) ? inline : outline;
|
|
140
|
-
if (text.some((p) => paragraphText(p).length > 0)) shapes.push({ paragraphs: text });
|
|
162
|
+
function slideShapes(slideData, img, outline, env, defaults) {
|
|
163
|
+
const content = collectShapes(slideData, img, env, outline, defaults);
|
|
164
|
+
if (!content.shapes.some(shapeHasText)) {
|
|
165
|
+
const inline = collectParagraphs(slideData, 0, defaults, env);
|
|
166
|
+
const text = inline.some((p) => paragraphText(p).length > 0) ? inline : outline.flat();
|
|
167
|
+
if (text.some((p) => paragraphText(p).length > 0)) content.shapes.push({ paragraphs: text });
|
|
141
168
|
}
|
|
142
|
-
return
|
|
169
|
+
return content;
|
|
143
170
|
}
|
|
144
171
|
function buildPersistDirectory(stream, currentEditOffset) {
|
|
145
172
|
const persist = /* @__PURE__ */ new Map();
|
|
@@ -178,42 +205,73 @@ function mergePersistDirectory(stream, offset, persist) {
|
|
|
178
205
|
}
|
|
179
206
|
}
|
|
180
207
|
function readSlideList(stream, docData, persist, img) {
|
|
208
|
+
const fonts = parseFontCollection(docData);
|
|
181
209
|
const slwt = findChild(docData, (r) => r.type === RT_SLIDE_LIST_WITH_TEXT && r.instance === SLWT_INSTANCE_SLIDES);
|
|
182
210
|
if (!slwt) return [];
|
|
183
211
|
const slides = [];
|
|
184
212
|
let outline = [];
|
|
185
213
|
let pendingRef;
|
|
214
|
+
const masters = {
|
|
215
|
+
persist,
|
|
216
|
+
stream,
|
|
217
|
+
byMasterId: buildMasterIdMap(docData),
|
|
218
|
+
cache: /* @__PURE__ */ new Map()
|
|
219
|
+
};
|
|
186
220
|
const flush = () => {
|
|
187
221
|
if (pendingRef === void 0) return;
|
|
188
222
|
const slideOff = persist.get(pendingRef);
|
|
189
223
|
const slideRec = slideOff !== void 0 ? recordAt(stream, slideOff) : void 0;
|
|
190
|
-
const
|
|
191
|
-
|
|
224
|
+
const isSlide = slideRec !== void 0 && slideRec.type === RT_SLIDE;
|
|
225
|
+
const scheme = isSlide ? resolveScheme(slideRec.data, masters) : void 0;
|
|
226
|
+
const env = {
|
|
227
|
+
...scheme ? { scheme } : {},
|
|
228
|
+
...fonts.length > 0 ? { fonts } : {}
|
|
229
|
+
};
|
|
230
|
+
const defaults = isSlide ? masterChain(slideRec.data, masters, scheme, fonts) : void 0;
|
|
231
|
+
const texts = outline.map((e) => styledParagraphs(e.rec, e.style, levelStyles(defaults, e.textType), env));
|
|
232
|
+
const flat = texts.flat();
|
|
233
|
+
const content = isSlide ? slideShapes(slideRec.data, img, texts, env, defaults) : { shapes: flat.some((p) => paragraphText(p).length > 0) ? [{ paragraphs: flat }] : [] };
|
|
234
|
+
const background = isSlide ? masterBackground(slideRec.data, masters, img) ?? content.background : void 0;
|
|
235
|
+
const decoration = isSlide ? masterShapes(slideRec.data, masters, img) : [];
|
|
236
|
+
slides.push({
|
|
237
|
+
shapes: [...decoration, ...content.shapes],
|
|
238
|
+
...background ? { background } : {}
|
|
239
|
+
});
|
|
192
240
|
outline = [];
|
|
193
241
|
pendingRef = void 0;
|
|
194
242
|
};
|
|
195
243
|
const recs = [...records(slwt)];
|
|
244
|
+
let textType = TEXT_TYPE_OTHER;
|
|
196
245
|
for (let i = 0; i < recs.length; i++) {
|
|
197
246
|
const rec = recs[i];
|
|
198
247
|
if (rec.type === RT_SLIDE_PERSIST_ATOM) {
|
|
199
248
|
flush();
|
|
200
249
|
pendingRef = rec.data.length >= 4 ? u32(rec.data, 0) : void 0;
|
|
201
|
-
} else if (rec.type ===
|
|
250
|
+
} else if (rec.type === RT_TEXT_HEADER_ATOM) textType = rec.data.length >= 4 ? u32(rec.data, 0) : TEXT_TYPE_OTHER;
|
|
251
|
+
else if (rec.type === RT_TEXT_CHARS_ATOM || rec.type === RT_TEXT_BYTES_ATOM) outline.push({
|
|
252
|
+
textType,
|
|
253
|
+
rec,
|
|
254
|
+
style: findFollowingStyle(recs, i)
|
|
255
|
+
});
|
|
202
256
|
}
|
|
203
257
|
flush();
|
|
204
258
|
return slides;
|
|
205
259
|
}
|
|
206
|
-
function collectParagraphs(d, depth) {
|
|
260
|
+
function collectParagraphs(d, depth, defaults, env) {
|
|
207
261
|
if (depth > MAX_DEPTH) return [];
|
|
208
262
|
const out = [];
|
|
209
263
|
const recs = [...records(d)];
|
|
264
|
+
let textType = TEXT_TYPE_OTHER;
|
|
210
265
|
for (let i = 0; i < recs.length; i++) {
|
|
211
266
|
const rec = recs[i];
|
|
212
|
-
if (rec.type ===
|
|
213
|
-
else if (rec.
|
|
267
|
+
if (rec.type === RT_TEXT_HEADER_ATOM) textType = rec.data.length >= 4 ? u32(rec.data, 0) : TEXT_TYPE_OTHER;
|
|
268
|
+
else if (rec.type === RT_TEXT_CHARS_ATOM || rec.type === RT_TEXT_BYTES_ATOM) out.push(...styledParagraphs(rec, findFollowingStyle(recs, i), levelStyles(defaults, textType), env));
|
|
269
|
+
else if (rec.isContainer) out.push(...collectParagraphs(rec.data, depth + 1, defaults, env));
|
|
214
270
|
}
|
|
215
271
|
return out;
|
|
216
272
|
}
|
|
273
|
+
var TEXT_TYPE_OTHER = 3;
|
|
274
|
+
var levelStyles = (defaults, textType) => defaults ? (level) => defaults(textType, level) : void 0;
|
|
217
275
|
function findFollowingStyle(recs, i) {
|
|
218
276
|
for (let j = i + 1; j < recs.length; j++) {
|
|
219
277
|
const t = recs[j].type;
|
|
@@ -221,8 +279,8 @@ function findFollowingStyle(recs, i) {
|
|
|
221
279
|
if (t === RT_TEXT_CHARS_ATOM || t === RT_TEXT_BYTES_ATOM || t === RT_TEXT_HEADER_ATOM) break;
|
|
222
280
|
}
|
|
223
281
|
}
|
|
224
|
-
function styledParagraphs(textRec, styleData) {
|
|
225
|
-
return buildStyledParagraphs(textRec.type === RT_TEXT_CHARS_ATOM ? decodeUtf16(textRec.data) : decodeCp1252(textRec.data), styleData);
|
|
282
|
+
function styledParagraphs(textRec, styleData, defaults, env) {
|
|
283
|
+
return buildStyledParagraphs(textRec.type === RT_TEXT_CHARS_ATOM ? decodeUtf16(textRec.data) : decodeCp1252(textRec.data), styleData, defaults, env);
|
|
226
284
|
}
|
|
227
285
|
function slidesByScan(stream, img) {
|
|
228
286
|
const slides = [];
|
|
@@ -231,8 +289,14 @@ function slidesByScan(stream, img) {
|
|
|
231
289
|
}
|
|
232
290
|
function collectSlides(d, out, img, depth) {
|
|
233
291
|
if (depth > MAX_DEPTH) return;
|
|
234
|
-
for (const rec of records(d)) if (rec.type === RT_SLIDE)
|
|
235
|
-
|
|
292
|
+
for (const rec of records(d)) if (rec.type === RT_SLIDE) {
|
|
293
|
+
const scheme = resolveScheme(rec.data);
|
|
294
|
+
const content = slideShapes(rec.data, img, [], scheme ? { scheme } : {});
|
|
295
|
+
out.push({
|
|
296
|
+
shapes: content.shapes,
|
|
297
|
+
...content.background ? { background: content.background } : {}
|
|
298
|
+
});
|
|
299
|
+
} else if (rec.isContainer) collectSlides(rec.data, out, img, depth + 1);
|
|
236
300
|
}
|
|
237
301
|
function findChild(d, pred) {
|
|
238
302
|
for (const rec of records(d)) if (pred(rec)) return rec.data;
|
|
@@ -288,53 +352,328 @@ function findDescendantContainer(d, type, depth) {
|
|
|
288
352
|
}
|
|
289
353
|
}
|
|
290
354
|
}
|
|
291
|
-
function collectShapes(slideData, img,
|
|
292
|
-
const out = [];
|
|
293
|
-
collectShapeContainers(slideData, img, out, 0,
|
|
355
|
+
function collectShapes(slideData, img, env, outline = [], defaults) {
|
|
356
|
+
const out = { shapes: [] };
|
|
357
|
+
collectShapeContainers(slideData, img, out, 0, env, outline, defaults);
|
|
294
358
|
return out;
|
|
295
359
|
}
|
|
296
|
-
function collectShapeContainers(d, img, out, depth,
|
|
360
|
+
function collectShapeContainers(d, img, out, depth, env, outline, defaults, group) {
|
|
361
|
+
const scheme = env.scheme;
|
|
297
362
|
if (depth > MAX_DEPTH) return;
|
|
298
|
-
for (const r of records(d))
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
let shapeType = 0;
|
|
303
|
-
let fspFlags = 0;
|
|
304
|
-
let fillColorHex;
|
|
305
|
-
let lineColorHex;
|
|
306
|
-
let geometry;
|
|
307
|
-
for (const child of records(r.data)) if (child.type === FBT_FSP) {
|
|
308
|
-
shapeType = child.instance;
|
|
309
|
-
fspFlags = child.data.length >= 8 ? u32(child.data, 4) : 0;
|
|
310
|
-
} else if (child.type === FBT_CLIENT_ANCHOR) rectPt = parseAnchor(child.data);
|
|
311
|
-
else if (child.type === FBT_CLIENT_TEXTBOX) paragraphs = collectParagraphs(child.data, 0);
|
|
312
|
-
else if (child.type === FBT_OPT) {
|
|
313
|
-
pib = optProperty(child.data, child.instance, PROP_PIB);
|
|
314
|
-
fillColorHex = optColor(child.data, child.instance, PROP_FILL_COLOR, scheme);
|
|
315
|
-
lineColorHex = optColor(child.data, child.instance, PROP_LINE_COLOR, scheme);
|
|
316
|
-
geometry = parseFreeformGeometry(child.data, child.instance);
|
|
363
|
+
for (const r of records(d)) {
|
|
364
|
+
if (r.type === FBT_SPGR_CONTAINER) {
|
|
365
|
+
collectShapeContainers(r.data, img, out, depth + 1, env, outline, defaults, groupFrame(r.data) ?? group);
|
|
366
|
+
continue;
|
|
317
367
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
368
|
+
if (r.type === FBT_SP_CONTAINER) {
|
|
369
|
+
let rectPt;
|
|
370
|
+
let paragraphs;
|
|
371
|
+
let pib;
|
|
372
|
+
let shapeType = 0;
|
|
373
|
+
let fspFlags = 0;
|
|
374
|
+
let fillColorHex;
|
|
375
|
+
let lineColorHex;
|
|
376
|
+
let gradient;
|
|
377
|
+
let geometry;
|
|
378
|
+
let fillType;
|
|
379
|
+
let fillBlip;
|
|
380
|
+
let inlineFill;
|
|
381
|
+
let inlinePic;
|
|
382
|
+
let tileSizePt;
|
|
383
|
+
let gtext;
|
|
384
|
+
let placeholder = false;
|
|
385
|
+
for (const child of records(r.data)) if (child.type === FBT_FSP) {
|
|
386
|
+
shapeType = child.instance;
|
|
387
|
+
fspFlags = child.data.length >= 8 ? u32(child.data, 4) : 0;
|
|
388
|
+
} else if (child.type === FBT_CLIENT_ANCHOR) rectPt = parseAnchor(child.data);
|
|
389
|
+
else if (child.type === FBT_CHILD_ANCHOR && group) rectPt = childRect(child.data, group);
|
|
390
|
+
else if (child.type === FBT_CLIENT_DATA) placeholder = findChild(child.data, (c) => c.type === RT_PLACEHOLDER_ATOM) !== void 0;
|
|
391
|
+
else if (child.type === FBT_CLIENT_TEXTBOX) paragraphs = clientTextboxParagraphs(child.data, outline, defaults, env);
|
|
392
|
+
else if (child.type === FBT_OPT) {
|
|
393
|
+
pib = optProperty(child.data, child.instance, PROP_PIB);
|
|
394
|
+
fillColorHex = stated(child.data, child.instance, PROP_FILL_BOOLS, FILL_F_FILLED) ? optColor(child.data, child.instance, PROP_FILL_COLOR, scheme) : void 0;
|
|
395
|
+
lineColorHex = stated(child.data, child.instance, PROP_LINE_BOOLS, LINE_F_LINE) ? optColor(child.data, child.instance, PROP_LINE_COLOR, scheme) : void 0;
|
|
396
|
+
gradient = parseFillGradient(child.data, child.instance, fillColorHex, scheme);
|
|
397
|
+
geometry = parseFreeformGeometry(child.data, child.instance);
|
|
398
|
+
fillType = optProperty(child.data, child.instance, PROP_FILL_TYPE);
|
|
399
|
+
fillBlip = optProperty(child.data, child.instance, PROP_FILL_BLIP);
|
|
400
|
+
tileSizePt = parseTileSize(child.data, child.instance);
|
|
401
|
+
gtext = parseWordArt(child.data, child.instance, fillColorHex);
|
|
402
|
+
inlineFill = optComplex(child.data, child.instance, PROP_FILL_BLIP);
|
|
403
|
+
inlinePic = optComplex(child.data, child.instance, PROP_PIB);
|
|
404
|
+
}
|
|
405
|
+
const blip = (index) => {
|
|
406
|
+
if (index === void 0 || index < 1 || index > img.foDelays.length) return void 0;
|
|
407
|
+
const bytes = readBlipBytes(img.pictures, img.foDelays[index - 1]);
|
|
408
|
+
return bytes ? { bytes } : void 0;
|
|
409
|
+
};
|
|
410
|
+
const tiled = fillType === 2;
|
|
411
|
+
const fillImage = fillType === 2 || fillType === 3 ? blip(fillBlip) ?? inlineBlip(inlineFill) : void 0;
|
|
412
|
+
if ((fspFlags & FSP_FLAG_BACKGROUND) !== 0) {
|
|
413
|
+
const bg = slideBackground(fillColorHex, gradient, fillType, fillImage, tiled);
|
|
414
|
+
if (bg && !out.background) out.background = bg;
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
const image = blip(pib) ?? inlineBlip(inlinePic);
|
|
418
|
+
const textParas = gtext ?? (paragraphs?.some((p) => paragraphText(p).length > 0) === true ? paragraphs : void 0) ? gtext ? [gtext] : paragraphs : void 0;
|
|
419
|
+
const decorative = (fspFlags & (FSP_FLAG_PATRIARCH | 1025)) === 0;
|
|
420
|
+
const autoShape = !gtext && !image && rectPt && (shapeType > 0 || geometry) && decorative && (fillColorHex || lineColorHex || fillImage) ? {
|
|
421
|
+
shapeType,
|
|
422
|
+
...fillColorHex ? { fillColorHex } : {},
|
|
423
|
+
...lineColorHex ? { lineColorHex } : {},
|
|
424
|
+
...gradient ? { gradient } : {},
|
|
425
|
+
...fillImage ? { image: fillImage } : {},
|
|
426
|
+
...fillImage && tiled ? { imageTiled: true } : {},
|
|
427
|
+
...fillImage && tiled && tileSizePt ? { tileSizePt } : {},
|
|
428
|
+
...geometry ? { geometry } : {}
|
|
429
|
+
} : void 0;
|
|
430
|
+
if (textParas || image || autoShape) out.shapes.push({
|
|
431
|
+
...rectPt ? { rectPt } : {},
|
|
432
|
+
...gtext ? { wordArt: true } : {},
|
|
433
|
+
...placeholder ? { placeholder: true } : {},
|
|
434
|
+
...textParas ? { paragraphs: textParas } : {},
|
|
435
|
+
...image ? { image } : {},
|
|
436
|
+
...autoShape ? { autoShape } : {}
|
|
437
|
+
});
|
|
438
|
+
} else if (r.isContainer) collectShapeContainers(r.data, img, out, depth + 1, env, outline, defaults, group);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function parseFontCollection(docData) {
|
|
442
|
+
const out = [];
|
|
443
|
+
const coll = findDescendantContainer(docData, RT_FONT_COLLECTION, 0);
|
|
444
|
+
if (!coll) return out;
|
|
445
|
+
let ordinal = 0;
|
|
446
|
+
for (const rec of records(coll)) {
|
|
447
|
+
if (rec.type !== RT_FONT_ENTITY_ATOM || rec.data.length < 2) continue;
|
|
448
|
+
const index = rec.instance > 0 || ordinal === 0 ? rec.instance : ordinal;
|
|
449
|
+
let name = "";
|
|
450
|
+
for (let i = 0; i < 32 && i * 2 + 1 < rec.data.length; i++) {
|
|
451
|
+
const cu = u16(rec.data, i * 2);
|
|
452
|
+
if (cu === 0) break;
|
|
453
|
+
name += String.fromCharCode(cu);
|
|
454
|
+
}
|
|
455
|
+
out[index] = name;
|
|
456
|
+
ordinal++;
|
|
457
|
+
}
|
|
458
|
+
return out;
|
|
459
|
+
}
|
|
460
|
+
function parseMasterTextStyles(masterData, fonts) {
|
|
461
|
+
const out = /* @__PURE__ */ new Map();
|
|
462
|
+
for (const rec of records(masterData)) {
|
|
463
|
+
if (rec.type !== RT_TEXT_MASTER_STYLE_ATOM || rec.data.length < 2) continue;
|
|
464
|
+
const levels = Math.min(u16(rec.data, 0), 5);
|
|
465
|
+
const first = readMasterLevels(rec.data, levels, rec.instance >= 4 ? 2 : 0, fonts);
|
|
466
|
+
const exact = (r) => r.styles.length === levels && r.off === rec.data.length;
|
|
467
|
+
let best = first;
|
|
468
|
+
if (!exact(first)) {
|
|
469
|
+
const other = readMasterLevels(rec.data, levels, rec.instance >= 4 ? 0 : 2, fonts);
|
|
470
|
+
if (exact(other)) best = other;
|
|
322
471
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
472
|
+
if (best.styles.length > 0) out.set(rec.instance, best.styles);
|
|
473
|
+
}
|
|
474
|
+
return out;
|
|
475
|
+
}
|
|
476
|
+
function readMasterLevels(d, levels, prefix, fonts) {
|
|
477
|
+
const styles = [];
|
|
478
|
+
let off = 2;
|
|
479
|
+
for (let i = 0; i < levels; i++) {
|
|
480
|
+
off += prefix;
|
|
481
|
+
if (off + 4 > d.length) break;
|
|
482
|
+
const pf = readPfException(d, off);
|
|
483
|
+
if (pf.off + 4 > d.length) break;
|
|
484
|
+
const cf = readCfException(d, pf.off, void 0, fonts);
|
|
485
|
+
if (cf.off > d.length) break;
|
|
486
|
+
off = cf.off;
|
|
487
|
+
styles.push({
|
|
488
|
+
...cf.props,
|
|
489
|
+
...pf.align !== void 0 ? { align: pf.align } : {},
|
|
490
|
+
...pf.bullet !== void 0 ? { bullet: pf.bullet } : {},
|
|
491
|
+
...pf.bulletOn !== void 0 ? { bulletOn: pf.bulletOn } : {}
|
|
336
492
|
});
|
|
337
|
-
}
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
styles,
|
|
496
|
+
off
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
var TEXT_TYPE_FALLBACK = new Map([
|
|
500
|
+
[4, 1],
|
|
501
|
+
[5, 0],
|
|
502
|
+
[6, 1],
|
|
503
|
+
[7, 1]
|
|
504
|
+
]);
|
|
505
|
+
function masterDefaults(chain, scheme) {
|
|
506
|
+
return (textType, level) => {
|
|
507
|
+
const types = [textType, TEXT_TYPE_FALLBACK.get(textType)];
|
|
508
|
+
let merged;
|
|
509
|
+
for (const styles of chain) for (const t of types) {
|
|
510
|
+
const levels = t === void 0 ? void 0 : styles.get(t);
|
|
511
|
+
const at = levels?.[Math.min(level, levels.length - 1)];
|
|
512
|
+
if (!at) continue;
|
|
513
|
+
const { colorHex: _c, colorIndex: _i, bullet: _b, bulletOn: _o, ...metrics } = at;
|
|
514
|
+
merged = {
|
|
515
|
+
...t === textType ? at : metrics,
|
|
516
|
+
...merged
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
if (!merged || merged.colorHex !== void 0 || merged.colorIndex === void 0) return merged;
|
|
520
|
+
const slot = scheme?.[merged.colorIndex];
|
|
521
|
+
return slot === void 0 ? merged : {
|
|
522
|
+
...merged,
|
|
523
|
+
colorHex: slot
|
|
524
|
+
};
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
function buildMasterIdMap(docData) {
|
|
528
|
+
const out = /* @__PURE__ */ new Map();
|
|
529
|
+
const slwt = findChild(docData, (r) => r.type === RT_SLIDE_LIST_WITH_TEXT && r.instance === SLWT_INSTANCE_MASTERS);
|
|
530
|
+
if (!slwt) return out;
|
|
531
|
+
for (const rec of records(slwt)) if (rec.type === RT_SLIDE_PERSIST_ATOM && rec.data.length >= 16) out.set(u32(rec.data, 12), u32(rec.data, 0));
|
|
532
|
+
return out;
|
|
533
|
+
}
|
|
534
|
+
var SLIDE_FLAG_MASTER_OBJECTS = 1;
|
|
535
|
+
var SLIDE_FLAG_MASTER_BACKGROUND = 4;
|
|
536
|
+
function masterOf(slideData, ctx) {
|
|
537
|
+
const slideAtom = findChild(slideData, (r) => r.type === RT_SLIDE_ATOM);
|
|
538
|
+
if (!slideAtom || slideAtom.length < 22) return void 0;
|
|
539
|
+
const id = u32(slideAtom, 12);
|
|
540
|
+
const off = ctx.persist.get(ctx.byMasterId.get(id) ?? id);
|
|
541
|
+
const rec = off !== void 0 ? recordAt(ctx.stream, off) : void 0;
|
|
542
|
+
return rec && (rec.type === RT_MAIN_MASTER || rec.type === RT_SLIDE) ? rec : void 0;
|
|
543
|
+
}
|
|
544
|
+
function slideFlag(slideData, flag) {
|
|
545
|
+
const slideAtom = findChild(slideData, (r) => r.type === RT_SLIDE_ATOM);
|
|
546
|
+
return slideAtom !== void 0 && slideAtom.length >= 22 && (u16(slideAtom, 20) & flag) !== 0;
|
|
547
|
+
}
|
|
548
|
+
function masterShapes(slideData, ctx, img) {
|
|
549
|
+
if (!slideFlag(slideData, SLIDE_FLAG_MASTER_OBJECTS)) return [];
|
|
550
|
+
const master = masterOf(slideData, ctx);
|
|
551
|
+
if (!master) return [];
|
|
552
|
+
const scheme = resolveScheme(master.data, ctx);
|
|
553
|
+
return collectShapes(master.data, img, scheme ? { scheme } : {}).shapes.filter((s) => s.placeholder !== true && s.rectPt !== void 0);
|
|
554
|
+
}
|
|
555
|
+
function masterBackground(slideData, ctx, img) {
|
|
556
|
+
if (!slideFlag(slideData, SLIDE_FLAG_MASTER_BACKGROUND)) return void 0;
|
|
557
|
+
const master = masterOf(slideData, ctx);
|
|
558
|
+
if (!master) return void 0;
|
|
559
|
+
const scheme = resolveScheme(master.data, ctx);
|
|
560
|
+
return collectShapes(master.data, img, scheme ? { scheme } : {}).background;
|
|
561
|
+
}
|
|
562
|
+
function masterChain(slideData, ctx, scheme, fonts) {
|
|
563
|
+
const chain = [];
|
|
564
|
+
if (!ctx) return masterDefaults(chain, scheme);
|
|
565
|
+
let data = slideData;
|
|
566
|
+
const seen = /* @__PURE__ */ new Set();
|
|
567
|
+
for (let hop = 0; hop < 4 && data; hop++) {
|
|
568
|
+
const slideAtom = findChild(data, (r) => r.type === RT_SLIDE_ATOM);
|
|
569
|
+
if (!slideAtom || slideAtom.length < 16) break;
|
|
570
|
+
const masterId = u32(slideAtom, 12);
|
|
571
|
+
if (seen.has(masterId)) break;
|
|
572
|
+
seen.add(masterId);
|
|
573
|
+
const cached = ctx.cache.get(masterId);
|
|
574
|
+
const off = ctx.persist.get(ctx.byMasterId.get(masterId) ?? masterId);
|
|
575
|
+
const rec = off !== void 0 ? recordAt(ctx.stream, off) : void 0;
|
|
576
|
+
if (!rec || rec.type !== RT_MAIN_MASTER && rec.type !== RT_SLIDE) break;
|
|
577
|
+
if (cached) chain.push(cached);
|
|
578
|
+
else {
|
|
579
|
+
const styles = parseMasterTextStyles(rec.data, fonts);
|
|
580
|
+
ctx.cache.set(masterId, styles);
|
|
581
|
+
chain.push(styles);
|
|
582
|
+
}
|
|
583
|
+
data = rec.type === RT_SLIDE ? rec.data : void 0;
|
|
584
|
+
}
|
|
585
|
+
return masterDefaults(chain, scheme);
|
|
586
|
+
}
|
|
587
|
+
function groupFrame(spgrData) {
|
|
588
|
+
const sp = [...records(spgrData)].find((r) => r.type === FBT_SP_CONTAINER);
|
|
589
|
+
if (!sp) return void 0;
|
|
590
|
+
let box;
|
|
591
|
+
let rect;
|
|
592
|
+
for (const child of records(sp.data)) if (child.type === FBT_SPGR && child.data.length >= 16) {
|
|
593
|
+
const x = i32(child.data, 0);
|
|
594
|
+
const y = i32(child.data, 4);
|
|
595
|
+
box = {
|
|
596
|
+
x,
|
|
597
|
+
y,
|
|
598
|
+
w: i32(child.data, 8) - x,
|
|
599
|
+
h: i32(child.data, 12) - y
|
|
600
|
+
};
|
|
601
|
+
} else if (child.type === FBT_CLIENT_ANCHOR) rect = parseAnchor(child.data);
|
|
602
|
+
if (!box || !rect || box.w <= 0 || box.h <= 0) return void 0;
|
|
603
|
+
return {
|
|
604
|
+
rect,
|
|
605
|
+
...box
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
function childRect(d, g) {
|
|
609
|
+
if (d.length < 16) return void 0;
|
|
610
|
+
const x1 = g.rect.x + (i32(d, 0) - g.x) / g.w * g.rect.w;
|
|
611
|
+
const y1 = g.rect.y + (i32(d, 4) - g.y) / g.h * g.rect.h;
|
|
612
|
+
const x2 = g.rect.x + (i32(d, 8) - g.x) / g.w * g.rect.w;
|
|
613
|
+
const y2 = g.rect.y + (i32(d, 12) - g.y) / g.h * g.rect.h;
|
|
614
|
+
const w = x2 - x1;
|
|
615
|
+
const h = y2 - y1;
|
|
616
|
+
return w > 0 && h > 0 && Math.abs(x1) < 5e3 && Math.abs(y1) < 5e3 ? {
|
|
617
|
+
x: x1,
|
|
618
|
+
y: y1,
|
|
619
|
+
w,
|
|
620
|
+
h
|
|
621
|
+
} : void 0;
|
|
622
|
+
}
|
|
623
|
+
function clientTextboxParagraphs(d, outline, defaults, env) {
|
|
624
|
+
const own = collectParagraphs(d, 0, defaults, env);
|
|
625
|
+
if (own.some((p) => paragraphText(p).length > 0)) return own;
|
|
626
|
+
const ref = findChild(d, (r) => r.type === RT_OUTLINE_TEXT_REF_ATOM);
|
|
627
|
+
if (!ref || ref.length < 4) return own;
|
|
628
|
+
return [...outline[u32(ref, 0)] ?? []];
|
|
629
|
+
}
|
|
630
|
+
function parseWordArt(d, count, colorHex) {
|
|
631
|
+
const text = utf16Property(optComplex(d, count, PROP_GTEXT_UNICODE));
|
|
632
|
+
if (text === void 0 || text.trim() === "") return void 0;
|
|
633
|
+
const raw = optProperty(d, count, PROP_GTEXT_SIZE);
|
|
634
|
+
const sizePt = raw === void 0 ? void 0 : Math.round(raw / 65536 * 10) / 10;
|
|
635
|
+
const font = utf16Property(optComplex(d, count, PROP_GTEXT_FONT));
|
|
636
|
+
return {
|
|
637
|
+
runs: [{
|
|
638
|
+
text,
|
|
639
|
+
...sizePt !== void 0 && sizePt > 0 ? { sizePt } : {},
|
|
640
|
+
...colorHex ? { colorHex } : {},
|
|
641
|
+
...font ? { fontFamily: font } : {}
|
|
642
|
+
}],
|
|
643
|
+
align: 1
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
function utf16Property(blob) {
|
|
647
|
+
if (!blob || blob.length < 2) return void 0;
|
|
648
|
+
let out = "";
|
|
649
|
+
for (let i = 0; i * 2 + 1 < blob.length; i++) {
|
|
650
|
+
const cu = u16(blob, i * 2);
|
|
651
|
+
if (cu === 0) break;
|
|
652
|
+
out += String.fromCharCode(cu);
|
|
653
|
+
}
|
|
654
|
+
return out.length > 0 ? out : void 0;
|
|
655
|
+
}
|
|
656
|
+
function parseTileSize(d, count) {
|
|
657
|
+
const w = signedLong(optProperty(d, count, PROP_FILL_WIDTH));
|
|
658
|
+
const h = signedLong(optProperty(d, count, PROP_FILL_HEIGHT));
|
|
659
|
+
if (w === void 0 || h === void 0 || w <= 0 || h <= 0) return void 0;
|
|
660
|
+
return {
|
|
661
|
+
widthPt: w / EMU_PER_POINT,
|
|
662
|
+
heightPt: h / EMU_PER_POINT
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function inlineBlip(blob) {
|
|
666
|
+
if (!blob || blob.length < 8) return void 0;
|
|
667
|
+
const bytes = readEscherBlip(u16(blob, 2), u16(blob, 0) >> 4, blob.subarray(8));
|
|
668
|
+
return bytes ? { bytes } : void 0;
|
|
669
|
+
}
|
|
670
|
+
function slideBackground(fillColorHex, gradient, fillType, image, tiled) {
|
|
671
|
+
if (image) return {
|
|
672
|
+
image,
|
|
673
|
+
...tiled ? { imageTiled: true } : {}
|
|
674
|
+
};
|
|
675
|
+
if (gradient) return { gradient };
|
|
676
|
+
if (fillColorHex) return { fillColorHex };
|
|
338
677
|
}
|
|
339
678
|
function parseAnchor(data) {
|
|
340
679
|
let top;
|
|
@@ -364,6 +703,11 @@ function parseAnchor(data) {
|
|
|
364
703
|
h
|
|
365
704
|
};
|
|
366
705
|
}
|
|
706
|
+
function stated(d, count, propId, flag) {
|
|
707
|
+
const bools = optProperty(d, count, propId);
|
|
708
|
+
if (bools === void 0) return true;
|
|
709
|
+
return (bools & flag << 16) !== 0 ? (bools & flag) !== 0 : true;
|
|
710
|
+
}
|
|
367
711
|
function optProperty(d, count, wantId) {
|
|
368
712
|
for (let i = 0; i < count && i * 6 + 6 <= d.length; i++) {
|
|
369
713
|
const id = u16(d, i * 6);
|
|
@@ -375,11 +719,29 @@ function optComplex(d, count, wantId) {
|
|
|
375
719
|
for (let i = 0; i < count && i * 6 + 6 <= d.length; i++) {
|
|
376
720
|
const id = u16(d, i * 6);
|
|
377
721
|
if ((id & 32768) === 0) continue;
|
|
378
|
-
const len = u32(d, i * 6 + 2);
|
|
722
|
+
const len = arrayBlobLength(d, offset, id & 16383, u32(d, i * 6 + 2));
|
|
379
723
|
if ((id & 16383) === wantId) return offset + len <= d.length && len > 0 ? d.subarray(offset, offset + len) : void 0;
|
|
380
724
|
offset += len;
|
|
381
725
|
}
|
|
382
726
|
}
|
|
727
|
+
var ARRAY_PROPS = new Set([
|
|
728
|
+
325,
|
|
729
|
+
326,
|
|
730
|
+
327,
|
|
731
|
+
329,
|
|
732
|
+
330,
|
|
733
|
+
337,
|
|
734
|
+
338,
|
|
735
|
+
339
|
|
736
|
+
]);
|
|
737
|
+
function arrayBlobLength(d, offset, id, len) {
|
|
738
|
+
if (!ARRAY_PROPS.has(id) || offset + 6 > d.length) return len;
|
|
739
|
+
const nElems = u16(d, offset);
|
|
740
|
+
const raw = u16(d, offset + 4);
|
|
741
|
+
const signed = raw >= 32768 ? raw - 65536 : raw;
|
|
742
|
+
const size = signed < 0 ? -signed >> 2 : signed;
|
|
743
|
+
return size > 0 && nElems > 0 && nElems * size === len ? len + 6 : len;
|
|
744
|
+
}
|
|
383
745
|
function arrayHeader(blob) {
|
|
384
746
|
if (blob.length < 6) return void 0;
|
|
385
747
|
const raw = u16(blob, 4);
|
|
@@ -501,6 +863,29 @@ var SYS_COLORS = new Map([
|
|
|
501
863
|
[23, "000000"],
|
|
502
864
|
[24, "FFFFE1"]
|
|
503
865
|
]);
|
|
866
|
+
/**
|
|
867
|
+
* MS-ODRAW §2.3.7.1 `fillType` — the sweep a shaded fill asks for, or
|
|
868
|
+
* `undefined` when the shape is filled with one flat colour (type 0) or with
|
|
869
|
+
* something this reader does not draw (a picture, a texture, a pattern).
|
|
870
|
+
*
|
|
871
|
+
* @param d The OPT record's data.
|
|
872
|
+
* @param count Its entry count (the record's instance).
|
|
873
|
+
* @param fromHex The resolved `fillColor` — one end of the sweep.
|
|
874
|
+
* @param scheme The slide's colour scheme, for a scheme-relative far end.
|
|
875
|
+
*/
|
|
876
|
+
function parseFillGradient(d, count, fromHex, scheme) {
|
|
877
|
+
const type = optProperty(d, count, PROP_FILL_TYPE);
|
|
878
|
+
if (type === void 0 || type < 4 || type > 8) return void 0;
|
|
879
|
+
const toHex = optColor(d, count, PROP_FILL_BACK_COLOR, scheme) ?? "FFFFFF";
|
|
880
|
+
if (fromHex === void 0) return void 0;
|
|
881
|
+
const raw = optProperty(d, count, PROP_FILL_ANGLE);
|
|
882
|
+
return {
|
|
883
|
+
fromHex,
|
|
884
|
+
toHex,
|
|
885
|
+
angleDeg: raw === void 0 ? 90 : 90 - (raw | 0) / 65536,
|
|
886
|
+
radial: type === 5 || type === 6
|
|
887
|
+
};
|
|
888
|
+
}
|
|
504
889
|
function optColor(d, count, wantId, scheme) {
|
|
505
890
|
const v = optProperty(d, count, wantId);
|
|
506
891
|
if (v === void 0) return void 0;
|
|
@@ -512,13 +897,14 @@ function optColor(d, count, wantId, scheme) {
|
|
|
512
897
|
}
|
|
513
898
|
if (flags === COLORREF_SYS_INDEX) return SYS_COLORS.get(v & 65535);
|
|
514
899
|
}
|
|
515
|
-
function resolveScheme(slideData,
|
|
900
|
+
function resolveScheme(slideData, ctx) {
|
|
516
901
|
let schemeData = findColorScheme(slideData);
|
|
517
902
|
const slideAtom = findChild(slideData, (r) => r.type === RT_SLIDE_ATOM);
|
|
518
|
-
if (slideAtom && slideAtom.length >= 22 &&
|
|
903
|
+
if (slideAtom && slideAtom.length >= 22 && ctx) {
|
|
519
904
|
if ((u16(slideAtom, 20) & SLIDE_FLAG_MASTER_SCHEME) !== 0) {
|
|
520
|
-
const
|
|
521
|
-
const
|
|
905
|
+
const id = u32(slideAtom, 12);
|
|
906
|
+
const masterOff = ctx.persist.get(ctx.byMasterId.get(id) ?? id);
|
|
907
|
+
const masterRec = masterOff !== void 0 ? recordAt(ctx.stream, masterOff) : void 0;
|
|
522
908
|
if (masterRec && masterRec.type === RT_MAIN_MASTER) {
|
|
523
909
|
const masterScheme = findColorScheme(masterRec.data);
|
|
524
910
|
if (masterScheme) schemeData = masterScheme;
|
|
@@ -541,33 +927,19 @@ function parseColorScheme(d) {
|
|
|
541
927
|
}
|
|
542
928
|
function readBlipBytes(pictures, foDelay) {
|
|
543
929
|
if (foDelay < 0 || foDelay + 8 > pictures.length) return void 0;
|
|
930
|
+
const verInstance = u16(pictures, foDelay);
|
|
931
|
+
const type = u16(pictures, foDelay + 2);
|
|
544
932
|
const recLen = u32(pictures, foDelay + 4);
|
|
545
933
|
const start = foDelay + 8;
|
|
546
934
|
const blip = pictures.subarray(start, Math.min(pictures.length, start + recLen));
|
|
547
|
-
|
|
548
|
-
for (let off = 0; off < limit; off++) for (const magic of IMAGE_MAGICS) if (matchesMagic(blip, off, magic)) return blip.subarray(off);
|
|
549
|
-
}
|
|
550
|
-
var IMAGE_MAGICS = [[
|
|
551
|
-
137,
|
|
552
|
-
80,
|
|
553
|
-
78,
|
|
554
|
-
71
|
|
555
|
-
], [
|
|
556
|
-
255,
|
|
557
|
-
216,
|
|
558
|
-
255
|
|
559
|
-
]];
|
|
560
|
-
function matchesMagic(d, off, magic) {
|
|
561
|
-
if (off + magic.length > d.length) return false;
|
|
562
|
-
for (let i = 0; i < magic.length; i++) if (d[off + i] !== magic[i]) return false;
|
|
563
|
-
return true;
|
|
935
|
+
return readEscherBlip(type, verInstance >> 4, blip);
|
|
564
936
|
}
|
|
565
937
|
/** The concatenated plain text of a paragraph's runs. */
|
|
566
938
|
function paragraphText(p) {
|
|
567
939
|
return p.runs.map((r) => r.text).join("");
|
|
568
940
|
}
|
|
569
|
-
function buildStyledParagraphs(text, styleData) {
|
|
570
|
-
const style = styleData ? parseStyleTextProp(styleData, text.length) : void 0;
|
|
941
|
+
function buildStyledParagraphs(text, styleData, defaults, env) {
|
|
942
|
+
const style = styleData ? parseStyleTextProp(styleData, text.length, env) : void 0;
|
|
571
943
|
const charProps = style ? expandCharProps(style.charRuns, text.length) : void 0;
|
|
572
944
|
const paraRuns = style?.paraRuns ?? [];
|
|
573
945
|
const paras = [];
|
|
@@ -582,10 +954,16 @@ function buildStyledParagraphs(text, styleData) {
|
|
|
582
954
|
const endParagraph = () => {
|
|
583
955
|
pushRun();
|
|
584
956
|
const meta = paraRuns[paraIndex];
|
|
957
|
+
const lvl = defaults?.(meta?.level ?? 0);
|
|
958
|
+
const align = meta?.align ?? lvl?.align;
|
|
959
|
+
const on = meta?.bulletOn ?? lvl?.bulletOn;
|
|
960
|
+
const char = meta?.bullet ?? lvl?.bullet;
|
|
961
|
+
const bullet = on === false ? void 0 : on === true ? char ?? "•" : char;
|
|
585
962
|
paras.push({
|
|
586
|
-
runs,
|
|
587
|
-
...
|
|
588
|
-
...meta?.level !== void 0 ? { level: meta.level } : {}
|
|
963
|
+
runs: lvl ? runs.map((r) => inherit(r, lvl)) : runs,
|
|
964
|
+
...align !== void 0 ? { align } : {},
|
|
965
|
+
...meta?.level !== void 0 ? { level: meta.level } : {},
|
|
966
|
+
...bullet !== void 0 ? { bullet } : {}
|
|
589
967
|
});
|
|
590
968
|
runs = [];
|
|
591
969
|
paraIndex++;
|
|
@@ -606,6 +984,17 @@ function buildStyledParagraphs(text, styleData) {
|
|
|
606
984
|
if (paras.length > 1 && paragraphText(paras[paras.length - 1]).length === 0) paras.pop();
|
|
607
985
|
return paras;
|
|
608
986
|
}
|
|
987
|
+
function inherit(run, lvl) {
|
|
988
|
+
const sizePt = run.sizePt ?? lvl.sizePt;
|
|
989
|
+
const colorHex = run.colorHex ?? lvl.colorHex;
|
|
990
|
+
const fontFamily = run.fontFamily ?? lvl.fontFamily;
|
|
991
|
+
return {
|
|
992
|
+
...run,
|
|
993
|
+
...sizePt !== void 0 ? { sizePt } : {},
|
|
994
|
+
...colorHex !== void 0 ? { colorHex } : {},
|
|
995
|
+
...fontFamily !== void 0 ? { fontFamily } : {}
|
|
996
|
+
};
|
|
997
|
+
}
|
|
609
998
|
function toRun(text, props) {
|
|
610
999
|
if (!props) return { text };
|
|
611
1000
|
return {
|
|
@@ -614,13 +1003,14 @@ function toRun(text, props) {
|
|
|
614
1003
|
...props.italic ? { italic: true } : {},
|
|
615
1004
|
...props.underline ? { underline: true } : {},
|
|
616
1005
|
...props.sizePt ? { sizePt: props.sizePt } : {},
|
|
617
|
-
...props.colorHex ? { colorHex: props.colorHex } : {}
|
|
1006
|
+
...props.colorHex ? { colorHex: props.colorHex } : {},
|
|
1007
|
+
...props.fontFamily ? { fontFamily: props.fontFamily } : {}
|
|
618
1008
|
};
|
|
619
1009
|
}
|
|
620
1010
|
function sameProps(a, b) {
|
|
621
1011
|
if (a === b) return true;
|
|
622
1012
|
if (!a || !b) return false;
|
|
623
|
-
return !!a.bold === !!b.bold && !!a.italic === !!b.italic && !!a.underline === !!b.underline && a.sizePt === b.sizePt && a.colorHex === b.colorHex;
|
|
1013
|
+
return !!a.bold === !!b.bold && !!a.italic === !!b.italic && !!a.underline === !!b.underline && a.sizePt === b.sizePt && a.colorHex === b.colorHex && a.fontFamily === b.fontFamily;
|
|
624
1014
|
}
|
|
625
1015
|
function expandCharProps(charRuns, textLen) {
|
|
626
1016
|
const out = [];
|
|
@@ -628,7 +1018,7 @@ function expandCharProps(charRuns, textLen) {
|
|
|
628
1018
|
while (out.length < textLen) out.push(charRuns[charRuns.length - 1] ?? { count: 0 });
|
|
629
1019
|
return out;
|
|
630
1020
|
}
|
|
631
|
-
function parseStyleTextProp(data, textLen) {
|
|
1021
|
+
function parseStyleTextProp(data, textLen, env) {
|
|
632
1022
|
const target = textLen + 1;
|
|
633
1023
|
let off = 0;
|
|
634
1024
|
const paraRuns = [];
|
|
@@ -636,32 +1026,14 @@ function parseStyleTextProp(data, textLen) {
|
|
|
636
1026
|
while (consumed < target && off + 10 <= data.length) {
|
|
637
1027
|
const count = u32(data, off);
|
|
638
1028
|
const level = u16(data, off + 4);
|
|
639
|
-
const
|
|
640
|
-
off
|
|
641
|
-
let align;
|
|
642
|
-
if ((mask & 15) !== 0) off += 2;
|
|
643
|
-
if ((mask & 128) !== 0) off += 2;
|
|
644
|
-
if ((mask & 16) !== 0) off += 2;
|
|
645
|
-
if ((mask & 64) !== 0) off += 2;
|
|
646
|
-
if ((mask & 32) !== 0) off += 4;
|
|
647
|
-
if ((mask & 2048) !== 0) {
|
|
648
|
-
align = u16(data, off);
|
|
649
|
-
off += 2;
|
|
650
|
-
}
|
|
651
|
-
if ((mask & 4096) !== 0) off += 2;
|
|
652
|
-
if ((mask & 8192) !== 0) off += 2;
|
|
653
|
-
if ((mask & 16384) !== 0) off += 2;
|
|
654
|
-
if ((mask & 256) !== 0) off += 2;
|
|
655
|
-
if ((mask & 1024) !== 0) off += 2;
|
|
656
|
-
if ((mask & 32768) !== 0) off += 2;
|
|
657
|
-
if ((mask & 1048576) !== 0) off += 2 + (off + 2 <= data.length ? u16(data, off) : 0) * 4;
|
|
658
|
-
if ((mask & 65536) !== 0) off += 2;
|
|
659
|
-
if ((mask & 917504) !== 0) off += 2;
|
|
660
|
-
if ((mask & 2097152) !== 0) off += 2;
|
|
1029
|
+
const pf = readPfException(data, off + 6);
|
|
1030
|
+
off = pf.off;
|
|
661
1031
|
paraRuns.push({
|
|
662
1032
|
count,
|
|
663
1033
|
level,
|
|
664
|
-
...align !== void 0 ? { align } : {}
|
|
1034
|
+
...pf.align !== void 0 ? { align: pf.align } : {},
|
|
1035
|
+
...pf.bullet !== void 0 ? { bullet: pf.bullet } : {},
|
|
1036
|
+
...pf.bulletOn !== void 0 ? { bulletOn: pf.bulletOn } : {}
|
|
665
1037
|
});
|
|
666
1038
|
consumed += count;
|
|
667
1039
|
if (count <= 0) break;
|
|
@@ -670,31 +1042,12 @@ function parseStyleTextProp(data, textLen) {
|
|
|
670
1042
|
consumed = 0;
|
|
671
1043
|
while (consumed < target && off + 8 <= data.length) {
|
|
672
1044
|
const count = u32(data, off);
|
|
673
|
-
const
|
|
674
|
-
off
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
if ((mask & 1) !== 0 && (style & 1) !== 0) run.bold = true;
|
|
680
|
-
if ((mask & 2) !== 0 && (style & 2) !== 0) run.italic = true;
|
|
681
|
-
if ((mask & 4) !== 0 && (style & 4) !== 0) run.underline = true;
|
|
682
|
-
}
|
|
683
|
-
if ((mask & 65536) !== 0) off += 2;
|
|
684
|
-
if ((mask & 2097152) !== 0) off += 2;
|
|
685
|
-
if ((mask & 4194304) !== 0) off += 2;
|
|
686
|
-
if ((mask & 8388608) !== 0) off += 2;
|
|
687
|
-
if ((mask & 131072) !== 0) {
|
|
688
|
-
const sz = u16(data, off);
|
|
689
|
-
off += 2;
|
|
690
|
-
if (sz > 0) run.sizePt = sz;
|
|
691
|
-
}
|
|
692
|
-
if ((mask & 262144) !== 0) {
|
|
693
|
-
if (off + 4 <= data.length && data[off + 3] === 254) run.colorHex = hex2(data[off]) + hex2(data[off + 1]) + hex2(data[off + 2]);
|
|
694
|
-
off += 4;
|
|
695
|
-
}
|
|
696
|
-
if ((mask & 524288) !== 0) off += 2;
|
|
697
|
-
charRuns.push(run);
|
|
1045
|
+
const cf = readCfException(data, off + 4, env?.scheme, env?.fonts);
|
|
1046
|
+
off = cf.off;
|
|
1047
|
+
charRuns.push({
|
|
1048
|
+
count,
|
|
1049
|
+
...cf.props
|
|
1050
|
+
});
|
|
698
1051
|
consumed += count;
|
|
699
1052
|
if (count <= 0) break;
|
|
700
1053
|
}
|
|
@@ -703,6 +1056,92 @@ function parseStyleTextProp(data, textLen) {
|
|
|
703
1056
|
charRuns
|
|
704
1057
|
} : void 0;
|
|
705
1058
|
}
|
|
1059
|
+
function readPfException(data, start) {
|
|
1060
|
+
const mask = u32(data, start);
|
|
1061
|
+
let off = start + 4;
|
|
1062
|
+
let align;
|
|
1063
|
+
let bulletOn;
|
|
1064
|
+
let bullet;
|
|
1065
|
+
if ((mask & 15) !== 0) {
|
|
1066
|
+
bulletOn = (u16(data, off) & 1) !== 0;
|
|
1067
|
+
off += 2;
|
|
1068
|
+
}
|
|
1069
|
+
if ((mask & 128) !== 0) {
|
|
1070
|
+
bullet = bulletCharacter(u16(data, off));
|
|
1071
|
+
off += 2;
|
|
1072
|
+
}
|
|
1073
|
+
if ((mask & 16) !== 0) off += 2;
|
|
1074
|
+
if ((mask & 64) !== 0) off += 2;
|
|
1075
|
+
if ((mask & 32) !== 0) off += 4;
|
|
1076
|
+
if ((mask & 2048) !== 0) {
|
|
1077
|
+
align = u16(data, off);
|
|
1078
|
+
off += 2;
|
|
1079
|
+
}
|
|
1080
|
+
if ((mask & 4096) !== 0) off += 2;
|
|
1081
|
+
if ((mask & 8192) !== 0) off += 2;
|
|
1082
|
+
if ((mask & 16384) !== 0) off += 2;
|
|
1083
|
+
if ((mask & 256) !== 0) off += 2;
|
|
1084
|
+
if ((mask & 1024) !== 0) off += 2;
|
|
1085
|
+
if ((mask & 32768) !== 0) off += 2;
|
|
1086
|
+
if ((mask & 1048576) !== 0) off += 2 + (off + 2 <= data.length ? u16(data, off) : 0) * 4;
|
|
1087
|
+
if ((mask & 65536) !== 0) off += 2;
|
|
1088
|
+
if ((mask & 917504) !== 0) off += 2;
|
|
1089
|
+
if ((mask & 2097152) !== 0) off += 2;
|
|
1090
|
+
return {
|
|
1091
|
+
off,
|
|
1092
|
+
...align !== void 0 ? { align } : {},
|
|
1093
|
+
...bullet !== void 0 ? { bullet } : {},
|
|
1094
|
+
...bulletOn !== void 0 ? { bulletOn } : {}
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
function bulletCharacter(code) {
|
|
1098
|
+
if (code === 0) return void 0;
|
|
1099
|
+
const ch = String.fromCharCode(code);
|
|
1100
|
+
return code < 8192 || code >= 61440 && code <= 61695 ? fromSymbolFont(ch, "Wingdings") : ch;
|
|
1101
|
+
}
|
|
1102
|
+
function readCfException(data, start, scheme, fonts) {
|
|
1103
|
+
const mask = u32(data, start);
|
|
1104
|
+
let off = start + 4;
|
|
1105
|
+
const props = {};
|
|
1106
|
+
if ((mask & 16055) !== 0) {
|
|
1107
|
+
const style = u16(data, off);
|
|
1108
|
+
off += 2;
|
|
1109
|
+
if ((mask & 1) !== 0 && (style & 1) !== 0) props.bold = true;
|
|
1110
|
+
if ((mask & 2) !== 0 && (style & 2) !== 0) props.italic = true;
|
|
1111
|
+
if ((mask & 4) !== 0 && (style & 4) !== 0) props.underline = true;
|
|
1112
|
+
}
|
|
1113
|
+
if ((mask & 65536) !== 0) {
|
|
1114
|
+
props.fontRef = u16(data, off);
|
|
1115
|
+
off += 2;
|
|
1116
|
+
}
|
|
1117
|
+
if ((mask & 2097152) !== 0) off += 2;
|
|
1118
|
+
if ((mask & 4194304) !== 0) off += 2;
|
|
1119
|
+
if ((mask & 8388608) !== 0) off += 2;
|
|
1120
|
+
if ((mask & 131072) !== 0) {
|
|
1121
|
+
const sz = u16(data, off);
|
|
1122
|
+
off += 2;
|
|
1123
|
+
if (sz > 0) props.sizePt = sz;
|
|
1124
|
+
}
|
|
1125
|
+
if ((mask & 262144) !== 0) {
|
|
1126
|
+
const index = off + 4 <= data.length ? data[off + 3] : void 0;
|
|
1127
|
+
if (index === 254) props.colorHex = hex2(data[off]) + hex2(data[off + 1]) + hex2(data[off + 2]);
|
|
1128
|
+
else if (index !== void 0 && index < 8) {
|
|
1129
|
+
props.colorIndex = index;
|
|
1130
|
+
const slot = scheme?.[index];
|
|
1131
|
+
if (slot !== void 0) props.colorHex = slot;
|
|
1132
|
+
}
|
|
1133
|
+
off += 4;
|
|
1134
|
+
}
|
|
1135
|
+
if ((mask & 524288) !== 0) off += 2;
|
|
1136
|
+
if (props.fontRef !== void 0) {
|
|
1137
|
+
const name = fonts?.[props.fontRef];
|
|
1138
|
+
if (name !== void 0 && name.length > 0) props.fontFamily = name;
|
|
1139
|
+
}
|
|
1140
|
+
return {
|
|
1141
|
+
off,
|
|
1142
|
+
props
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
706
1145
|
function hex2(n) {
|
|
707
1146
|
return n.toString(16).padStart(2, "0").toUpperCase();
|
|
708
1147
|
}
|