reamkit 1.21.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.
Files changed (90) hide show
  1. package/dist/esm/core/bytes.d.ts +22 -4
  2. package/dist/esm/core/bytes.js +73 -5
  3. package/dist/esm/core/converter/ream.d.ts +16 -0
  4. package/dist/esm/core/converter/ream.js +59 -9
  5. package/dist/esm/core/document-model/types.d.ts +78 -0
  6. package/dist/esm/core/drawingml/chart-geometry.js +11 -5
  7. package/dist/esm/core/drawingml/chart-parser.d.ts +2 -1
  8. package/dist/esm/core/drawingml/chart-parser.js +23 -1
  9. package/dist/esm/core/drawingml/colors.d.ts +30 -4
  10. package/dist/esm/core/drawingml/colors.js +45 -6
  11. package/dist/esm/core/drawingml/preset-geometry.js +236 -0
  12. package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
  13. package/dist/esm/core/drawingml/theme-parser.js +64 -1
  14. package/dist/esm/core/fonts/families.d.ts +10 -0
  15. package/dist/esm/core/fonts/families.js +44 -0
  16. package/dist/esm/core/fonts/index.d.ts +3 -2
  17. package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
  18. package/dist/esm/core/fonts/remote-fonts.js +114 -8
  19. package/dist/esm/core/fonts/scripts.d.ts +26 -0
  20. package/dist/esm/core/fonts/scripts.js +177 -0
  21. package/dist/esm/core/metafile/blit.d.ts +33 -0
  22. package/dist/esm/core/metafile/blit.js +67 -0
  23. package/dist/esm/core/metafile/dib.d.ts +61 -0
  24. package/dist/esm/core/metafile/dib.js +205 -0
  25. package/dist/esm/core/metafile/emf.js +139 -24
  26. package/dist/esm/core/metafile/picture.d.ts +12 -1
  27. package/dist/esm/core/metafile/symbol-fonts.d.ts +42 -0
  28. package/dist/esm/core/metafile/symbol-fonts.js +154 -0
  29. package/dist/esm/core/metafile/wmf.js +183 -10
  30. package/dist/esm/core/ole/escher-blip.d.ts +12 -0
  31. package/dist/esm/core/ole/escher-blip.js +88 -0
  32. package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
  33. package/dist/esm/core/vector.d.ts +5 -0
  34. package/dist/esm/excel/print-model.js +3 -1
  35. package/dist/esm/excel/sheet-shape-parser.js +1 -12
  36. package/dist/esm/excel/styles-parser.js +1 -1
  37. package/dist/esm/excel/xls/biff-reader.js +53 -18
  38. package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
  39. package/dist/esm/excel/xls/biff-styles.js +9 -7
  40. package/dist/esm/excel/xls/escher.js +90 -24
  41. package/dist/esm/excel/xlsx-reader.d.ts +1 -1
  42. package/dist/esm/excel/xlsx-reader.js +3 -3
  43. package/dist/esm/layout/page-doc.d.ts +77 -0
  44. package/dist/esm/layout/page-doc.js +34 -18
  45. package/dist/esm/layout/styled-layout.d.ts +2 -2
  46. package/dist/esm/layout/styled-layout.js +467 -76
  47. package/dist/esm/pdf/shading.d.ts +19 -0
  48. package/dist/esm/pdf/shading.js +84 -11
  49. package/dist/esm/pdf/styled-page-emitter.js +647 -444
  50. package/dist/esm/pdf-reader/image-decode.js +1 -1
  51. package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
  52. package/dist/esm/pptx/embedded-fonts.js +104 -0
  53. package/dist/esm/pptx/ole-preview.d.ts +10 -0
  54. package/dist/esm/pptx/ole-preview.js +52 -0
  55. package/dist/esm/pptx/placeholder-cascade.d.ts +136 -5
  56. package/dist/esm/pptx/placeholder-cascade.js +260 -27
  57. package/dist/esm/pptx/ppt/ppt-reader.js +120 -10
  58. package/dist/esm/pptx/ppt/ppt-text.d.ts +66 -1
  59. package/dist/esm/pptx/ppt/ppt-text.js +576 -137
  60. package/dist/esm/pptx/pptx-reader.d.ts +8 -0
  61. package/dist/esm/pptx/pptx-reader.js +271 -41
  62. package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
  63. package/dist/esm/pptx/preset-table-styles.js +27 -0
  64. package/dist/esm/pptx/slide-parser.d.ts +78 -10
  65. package/dist/esm/pptx/slide-parser.js +396 -95
  66. package/dist/esm/pptx/sp-helpers.d.ts +2 -1
  67. package/dist/esm/pptx/sp-helpers.js +22 -6
  68. package/dist/esm/pptx/table-style.d.ts +64 -0
  69. package/dist/esm/pptx/table-style.js +203 -0
  70. package/dist/esm/svg/svg-writer.js +53 -5
  71. package/dist/esm/word/document-parser.d.ts +7 -1
  72. package/dist/esm/word/document-parser.js +6 -6
  73. package/dist/esm/word/docx-reader.js +8 -5
  74. package/dist/esm/word/docx-to-pdf.d.ts +8 -7
  75. package/dist/esm/word/docx-to-pdf.js +25 -7
  76. package/dist/esm/word/drawing-parser.d.ts +34 -0
  77. package/dist/esm/word/drawing-parser.js +173 -15
  78. package/dist/esm/word/numbering-parser.d.ts +2 -1
  79. package/dist/esm/word/numbering-parser.js +6 -6
  80. package/dist/esm/word/paragraph-properties.d.ts +2 -1
  81. package/dist/esm/word/paragraph-properties.js +2 -2
  82. package/dist/esm/word/run-properties.d.ts +5 -2
  83. package/dist/esm/word/run-properties.js +13 -8
  84. package/dist/esm/word/styles-parser.d.ts +2 -1
  85. package/dist/esm/word/styles-parser.js +12 -12
  86. package/dist/esm/word/table-parser.js +3 -3
  87. package/dist/esm/word/theme-fonts.d.ts +10 -0
  88. package/dist/esm/word/theme-fonts.js +28 -0
  89. package/package.json +1 -1
  90. /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, scheme) {
136
- const shapes = collectShapes(slideData, img, scheme);
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 shapes;
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 shapes = slideRec !== void 0 && slideRec.type === RT_SLIDE ? slideShapes(slideRec.data, img, outline, resolveScheme(slideRec.data, persist, stream)) : outline.some((p) => paragraphText(p).length > 0) ? [{ paragraphs: outline }] : [];
191
- slides.push({ shapes });
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 === RT_TEXT_CHARS_ATOM || rec.type === RT_TEXT_BYTES_ATOM) outline.push(...styledParagraphs(rec, findFollowingStyle(recs, i)));
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 === RT_TEXT_CHARS_ATOM || rec.type === RT_TEXT_BYTES_ATOM) out.push(...styledParagraphs(rec, findFollowingStyle(recs, i)));
213
- else if (rec.isContainer) out.push(...collectParagraphs(rec.data, depth + 1));
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) out.push({ shapes: slideShapes(rec.data, img, [], resolveScheme(rec.data)) });
235
- else if (rec.isContainer) collectSlides(rec.data, out, img, depth + 1);
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, scheme) {
292
- const out = [];
293
- collectShapeContainers(slideData, img, out, 0, scheme);
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, scheme) {
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)) if (r.type === FBT_SP_CONTAINER) {
299
- let rectPt;
300
- let paragraphs;
301
- let pib;
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
- let image;
319
- if (pib !== void 0 && pib >= 1 && pib <= img.foDelays.length) {
320
- const bytes = readBlipBytes(img.pictures, img.foDelays[pib - 1]);
321
- if (bytes) image = { bytes };
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
- const textParas = paragraphs && paragraphs.some((p) => paragraphText(p).length > 0) ? paragraphs : void 0;
324
- const decorative = (fspFlags & (FSP_FLAG_PATRIARCH | 1025)) === 0;
325
- const autoShape = !textParas && !image && rectPt && (shapeType > 0 || geometry) && decorative && (fillColorHex || lineColorHex) ? {
326
- shapeType,
327
- ...fillColorHex ? { fillColorHex } : {},
328
- ...lineColorHex ? { lineColorHex } : {},
329
- ...geometry ? { geometry } : {}
330
- } : void 0;
331
- if (textParas || image || autoShape) out.push({
332
- ...rectPt ? { rectPt } : {},
333
- ...textParas ? { paragraphs: textParas } : {},
334
- ...image ? { image } : {},
335
- ...autoShape ? { autoShape } : {}
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
- } else if (r.isContainer) collectShapeContainers(r.data, img, out, depth + 1, scheme);
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, persist, stream) {
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 && persist && stream) {
903
+ if (slideAtom && slideAtom.length >= 22 && ctx) {
519
904
  if ((u16(slideAtom, 20) & SLIDE_FLAG_MASTER_SCHEME) !== 0) {
520
- const masterOff = persist.get(u32(slideAtom, 12));
521
- const masterRec = masterOff !== void 0 ? recordAt(stream, masterOff) : void 0;
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
- const limit = Math.min(blip.length, 80);
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
- ...meta?.align !== void 0 ? { align: meta.align } : {},
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 mask = u32(data, off + 6);
640
- off += 10;
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 mask = u32(data, off + 4);
674
- off += 8;
675
- const run = { count };
676
- if ((mask & 16055) !== 0) {
677
- const style = u16(data, off);
678
- off += 2;
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
  }