reamkit 1.33.2 → 1.34.1

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 (71) hide show
  1. package/README.md +13 -10
  2. package/dist/esm/core/converter/facade.js +1 -0
  3. package/dist/esm/core/converter/ream.d.ts +6 -6
  4. package/dist/esm/core/converter/ream.js +11 -5
  5. package/dist/esm/core/document-model/index.d.ts +1 -1
  6. package/dist/esm/core/document-model/types.d.ts +15 -0
  7. package/dist/esm/core/drawingml/text-warp.d.ts +34 -0
  8. package/dist/esm/core/drawingml/text-warp.js +49 -1
  9. package/dist/esm/core/font/index.d.ts +1 -1
  10. package/dist/esm/core/font/index.js +8 -0
  11. package/dist/esm/core/font/indic-shaper.d.ts +47 -0
  12. package/dist/esm/core/font/indic-shaper.js +1146 -0
  13. package/dist/esm/core/font/indic-table.d.ts +12 -0
  14. package/dist/esm/core/font/indic-table.js +463 -0
  15. package/dist/esm/core/font/measure.d.ts +45 -4
  16. package/dist/esm/core/font/measure.js +253 -14
  17. package/dist/esm/core/font/opentype-lookups.d.ts +214 -0
  18. package/dist/esm/core/font/opentype-lookups.js +1112 -0
  19. package/dist/esm/core/fonts/families.d.ts +4 -0
  20. package/dist/esm/core/fonts/families.js +43 -12
  21. package/dist/esm/core/fonts/provider.js +1 -0
  22. package/dist/esm/core/fonts/remote-fonts.d.ts +4 -2
  23. package/dist/esm/core/fonts/remote-fonts.js +36 -0
  24. package/dist/esm/core/fonts/scripts.d.ts +19 -0
  25. package/dist/esm/core/fonts/scripts.js +96 -1
  26. package/dist/esm/core/numbering/apply.js +12 -8
  27. package/dist/esm/core/style-cascade/index.d.ts +1 -1
  28. package/dist/esm/core/style-cascade/index.js +2 -2
  29. package/dist/esm/core/style-cascade/resolver.d.ts +9 -0
  30. package/dist/esm/core/style-cascade/resolver.js +31 -3
  31. package/dist/esm/core/style-cascade/table.js +3 -8
  32. package/dist/esm/excel/xlsx-to-pdf.js +1 -0
  33. package/dist/esm/index.js +1 -0
  34. package/dist/esm/layout/line-paint.d.ts +5 -4
  35. package/dist/esm/layout/line-paint.js +6 -5
  36. package/dist/esm/layout/page-doc.d.ts +26 -0
  37. package/dist/esm/layout/styled-layout.d.ts +8 -1
  38. package/dist/esm/layout/styled-layout.js +459 -112
  39. package/dist/esm/layout/undrawn.d.ts +18 -0
  40. package/dist/esm/layout/undrawn.js +59 -0
  41. package/dist/esm/pdf/cid-font.d.ts +5 -0
  42. package/dist/esm/pdf/cid-font.js +8 -2
  43. package/dist/esm/pdf/styled-page-emitter.js +117 -28
  44. package/dist/esm/pdf/text-page-renderer.js +1 -0
  45. package/dist/esm/pdf-reader/content.d.ts +1 -1
  46. package/dist/esm/pdf-reader/content.js +48 -13
  47. package/dist/esm/pdf-reader/embedded-fonts.js +1 -0
  48. package/dist/esm/pdf-reader/encodings.d.ts +9 -0
  49. package/dist/esm/pdf-reader/encodings.js +66 -1
  50. package/dist/esm/pdf-reader/face-outlines.js +1 -0
  51. package/dist/esm/pdf-reader/text.d.ts +10 -0
  52. package/dist/esm/pdf-reader/text.js +25 -3
  53. package/dist/esm/pdf-reader/vector.js +2 -2
  54. package/dist/esm/pptx/embedded-fonts.js +1 -0
  55. package/dist/esm/pptx/sp-helpers.js +4 -1
  56. package/dist/esm/svg/svg-text.js +30 -7
  57. package/dist/esm/word/doc/doc-reader.js +148 -57
  58. package/dist/esm/word/doc/doc-text.d.ts +80 -11
  59. package/dist/esm/word/doc/doc-text.js +438 -75
  60. package/dist/esm/word/document-parser.js +48 -28
  61. package/dist/esm/word/docx-to-pdf.d.ts +5 -5
  62. package/dist/esm/word/docx-to-pdf.js +9 -7
  63. package/dist/esm/word/docx-writer.js +3 -5
  64. package/dist/esm/word/font-embed.js +1 -0
  65. package/dist/esm/word/font-table.js +1 -0
  66. package/dist/esm/word/numbering-parser.js +3 -0
  67. package/dist/esm/word/paragraph-properties.js +2 -2
  68. package/dist/esm/word/run-properties.js +2 -2
  69. package/dist/esm/word/xml-helpers.d.ts +18 -0
  70. package/dist/esm/word/xml-helpers.js +48 -1
  71. package/package.json +7 -2
@@ -7,6 +7,12 @@ var OFF_CCPFTN = 80;
7
7
  var OFF_CCPHDD = 84;
8
8
  var OFF_FCPLCFHDD = 242;
9
9
  var OFF_LCBPLCFHDD = 246;
10
+ var OFF_FCDOP = 402;
11
+ var OFF_LCBDOP = 406;
12
+ var OFF_FCSTSHF = 162;
13
+ var OFF_LCBSTSHF = 166;
14
+ var OFF_FCSTTBFFFN = 274;
15
+ var OFF_LCBSTTBFFFN = 278;
10
16
  var OFF_FCPLCFBTECHPX = 250;
11
17
  var OFF_LCBPLCFBTECHPX = 254;
12
18
  var OFF_FCPLCFBTEPAPX = 258;
@@ -31,6 +37,11 @@ var SPRM_C_KUL = 10814;
31
37
  var SPRM_C_HPS = 19011;
32
38
  var SPRM_C_FSPEC = 2133;
33
39
  var SPRM_C_PIC_LOCATION = 27139;
40
+ var SPRM_C_ISTD = 18992;
41
+ var SPRM_C_RG_FTC0 = 19023;
42
+ var SPRM_C_RG_FTC1 = 19024;
43
+ var SPRM_C_RG_FTC2 = 19025;
44
+ var SPRM_C_FTC_BI = 19038;
34
45
  var PIC_CHAR = 1;
35
46
  var SPRM_P_JC = 9219;
36
47
  var SPRM_P_DXA_RIGHT = 33806;
@@ -43,13 +54,26 @@ var SPRM_P_F_TTP = 9239;
43
54
  var SPRM_P_F_WIDOW_CONTROL = 9265;
44
55
  var SPRM_P_F_KEEP = 9221;
45
56
  var SPRM_P_F_KEEP_FOLLOW = 9222;
57
+ var SPRM_P_F_PAGE_BREAK_BEFORE = 9223;
46
58
  var SPRM_T_DEF_TABLE = 54792;
47
59
  var SPRM_T_DEF_TABLE_SHD = 54802;
48
60
  var MAX_ROW_CELLS = 256;
49
61
  var SPRM_P_ILVL = 9738;
50
62
  var SPRM_P_ILFO = 17931;
63
+ var SPRM_S_BKC = 12297;
64
+ var SPRM_S_F_TITLE_PAGE = 12298;
65
+ var SPRM_S_NFC_PGN = 12302;
66
+ var SPRM_S_F_PGN_RESTART = 12305;
67
+ var SPRM_S_PGN_START_97 = 20508;
51
68
  var SPRM_S_XA_PAGE = 45087;
52
69
  var SPRM_S_YA_PAGE = 45088;
70
+ var SPRM_S_DXA_LEFT = 45089;
71
+ var SPRM_S_DXA_RIGHT = 45090;
72
+ var SPRM_S_DYA_TOP = 36899;
73
+ var SPRM_S_DYA_BOTTOM = 36900;
74
+ var SPRM_S_DYA_HDR_TOP = 45079;
75
+ var SPRM_S_DYA_HDR_BOTTOM = 45080;
76
+ var SPRM_S_DZA_GUTTER = 45093;
53
77
  var MAX_PAGE_TWIPS = 31680;
54
78
  var SPRA_LEN = [
55
79
  1,
@@ -63,35 +87,88 @@ var SPRA_LEN = [
63
87
  ];
64
88
  var SPRM_LONG_OPERAND = /* @__PURE__ */ new Set([54792, 50701]);
65
89
  var CELL_MARK = 7;
90
+ var PAGE_BREAK = 12;
91
+ var COLUMN_BREAK = 14;
92
+ var LINE_BREAK = 11;
66
93
  var FIELD_BEGIN = 19;
67
94
  var FIELD_SEPARATOR = 20;
68
95
  var FIELD_END = 21;
96
+ var MAX_FIELD_INSTR = 64;
69
97
  var MAX_TEXT = 1 << 24;
98
+ var STK_PARAGRAPH = 1;
99
+ var STK_CHARACTER = 2;
100
+ var ISTD_NIL = 4095;
101
+ var MAX_STYLE_DEPTH = 16;
70
102
  var EMPTY = {
71
103
  paragraphs: [],
72
104
  encrypted: false
73
105
  };
74
- function readSectionPageSize(wd, table) {
106
+ function readSections(wd, table) {
107
+ const sections = [];
108
+ const ends = /* @__PURE__ */ new Map();
75
109
  const fc = u32(wd, OFF_FCPLCFSED);
76
110
  const lcb = u32(wd, OFF_LCBPLCFSED);
77
- if (lcb < 20 || fc + lcb > table.length) return void 0;
78
- const fcSepx = u32(table.subarray(fc, fc + lcb), (Math.floor((lcb - 4) / 16) + 1) * 4 + 2);
79
- if (fcSepx === 4294967295 || fcSepx + 2 > wd.length) return void 0;
80
- const cb = u16(wd, fcSepx);
81
- const grpprl = wd.subarray(fcSepx + 2, Math.min(wd.length, fcSepx + 2 + cb));
82
- let xa = 0;
83
- let ya = 0;
84
- for (const { sprm, op } of sprms(grpprl)) if (sprm === SPRM_S_XA_PAGE) xa = u16(grpprl, op);
85
- else if (sprm === SPRM_S_YA_PAGE) ya = u16(grpprl, op);
86
- if (xa < 1 || ya < 1 || xa > MAX_PAGE_TWIPS || ya > MAX_PAGE_TWIPS) return void 0;
111
+ if (lcb < 20 || fc + lcb > table.length) return {
112
+ sections,
113
+ ends
114
+ };
115
+ const plc = table.subarray(fc, fc + lcb);
116
+ const n = Math.floor((lcb - 4) / 16);
117
+ for (let i = 0; i < n; i++) {
118
+ if (i + 1 < n) ends.set(u32(plc, (i + 1) * 4), i);
119
+ const fcSepx = u32(plc, (n + 1) * 4 + i * 12 + 2);
120
+ if (fcSepx === 4294967295 || fcSepx + 2 > wd.length) {
121
+ sections.push({});
122
+ continue;
123
+ }
124
+ const cb = u16(wd, fcSepx);
125
+ const grpprl = wd.subarray(fcSepx + 2, Math.min(wd.length, fcSepx + 2 + cb));
126
+ let bkc;
127
+ let titlePage;
128
+ let nfcPgn;
129
+ let restart = false;
130
+ let pgnStart = 1;
131
+ let xa = 0;
132
+ let ya = 0;
133
+ const margins = {};
134
+ const margin = (key, twips) => {
135
+ if (twips <= MAX_PAGE_TWIPS) margins[key] = twips;
136
+ };
137
+ for (const { sprm, op } of sprms(grpprl)) if (sprm === SPRM_S_BKC) bkc = grpprl[op];
138
+ else if (sprm === SPRM_S_F_TITLE_PAGE) titlePage = grpprl[op] !== 0;
139
+ else if (sprm === SPRM_S_NFC_PGN) nfcPgn = grpprl[op];
140
+ else if (sprm === SPRM_S_F_PGN_RESTART) restart = grpprl[op] !== 0;
141
+ else if (sprm === SPRM_S_PGN_START_97) pgnStart = u16(grpprl, op);
142
+ else if (sprm === SPRM_S_XA_PAGE) xa = u16(grpprl, op);
143
+ else if (sprm === SPRM_S_YA_PAGE) ya = u16(grpprl, op);
144
+ else if (sprm === SPRM_S_DXA_LEFT) margin("leftTwips", u16(grpprl, op));
145
+ else if (sprm === SPRM_S_DXA_RIGHT) margin("rightTwips", u16(grpprl, op));
146
+ else if (sprm === SPRM_S_DYA_TOP) margin("topTwips", Math.abs(i16(grpprl, op)));
147
+ else if (sprm === SPRM_S_DYA_BOTTOM) margin("bottomTwips", Math.abs(i16(grpprl, op)));
148
+ else if (sprm === SPRM_S_DYA_HDR_TOP) margin("headerTwips", u16(grpprl, op));
149
+ else if (sprm === SPRM_S_DYA_HDR_BOTTOM) margin("footerTwips", u16(grpprl, op));
150
+ else if (sprm === SPRM_S_DZA_GUTTER) margin("gutterTwips", u16(grpprl, op));
151
+ const sane = xa >= 1 && ya >= 1 && xa <= MAX_PAGE_TWIPS && ya <= MAX_PAGE_TWIPS;
152
+ sections.push({
153
+ ...bkc !== void 0 ? { bkc } : {},
154
+ ...sane ? { pageSize: {
155
+ widthPt: xa / 20,
156
+ heightPt: ya / 20
157
+ } } : {},
158
+ ...titlePage ? { titlePage } : {},
159
+ ...Object.keys(margins).length > 0 ? { margins } : {},
160
+ ...restart ? { pageNumberStart: pgnStart } : {},
161
+ ...nfcPgn ? { pageNumberNfc: nfcPgn } : {}
162
+ });
163
+ }
87
164
  return {
88
- widthPt: xa / 20,
89
- heightPt: ya / 20
165
+ sections,
166
+ ends
90
167
  };
91
168
  }
92
169
  /**
93
170
  * Extract a `.doc`'s `WordDocument` stream into its main-document paragraphs plus
94
- * the section's header/footer stories, list tables and first-section page size.
171
+ * the section's header/footer stories, list tables and sections.
95
172
  * Joins the piece table (CLX → CPs/FCs), CHPX run formatting and PAPX paragraph
96
173
  * formatting, splitting at the CR / cell marks. Every offset is bounds-checked, so
97
174
  * a structurally odd file yields no text rather than throwing.
@@ -121,22 +198,160 @@ function extractDocContent(bytes) {
121
198
  const plcPcd = findPlcPcd(table.subarray(fcClx, fcClx + lcbClx));
122
199
  if (!plcPcd) return EMPTY;
123
200
  const pieces = parsePieces(plcPcd);
124
- const chpx = parsePlcBte(wd, table, OFF_FCPLCFBTECHPX, OFF_LCBPLCFBTECHPX, parseChpxFkp);
201
+ const fonts = readFonts(wd, table);
202
+ const chpx = parsePlcBte(wd, table, OFF_FCPLCFBTECHPX, OFF_LCBPLCFBTECHPX, (page, out) => parseChpxFkp(page, out, fonts));
125
203
  const papx = parsePlcBte(wd, table, OFF_FCPLCFBTEPAPX, OFF_LCBPLCFBTEPAPX, parsePapxFkp);
126
204
  const ccpText = u32(wd, OFF_CCPTEXT);
127
205
  const data = cfb.readStream("Data");
128
- const main = buildParagraphs(wd, pieces, chpx, papx, 0, ccpText, data);
129
- const headerFooters = extractHeaderFooters(wd, table, pieces, chpx, papx, data, ccpText);
206
+ const { sections, ends } = readSections(wd, table);
207
+ const styles = parseStyles(wd, table, fonts);
208
+ const main = buildParagraphs(wd, pieces, chpx, papx, 0, ccpText, data, ends, styles, fonts);
209
+ const headerFooters = extractHeaderFooters(wd, table, pieces, chpx, papx, data, ccpText, Math.max(1, sections.length), styles, fonts);
130
210
  const listTables = parseListTables(wd, table);
131
- const pageSize = readSectionPageSize(wd, table);
211
+ const fcDop = u32(wd, OFF_FCDOP);
212
+ const facingPages = u32(wd, OFF_LCBDOP) > 0 && fcDop < table.length && (table[fcDop] & 1) !== 0;
132
213
  return {
133
214
  paragraphs: main,
134
215
  ...headerFooters ? { headerFooters } : {},
216
+ ...facingPages ? { facingPages } : {},
135
217
  ...listTables ? { listTables } : {},
136
- ...pageSize ? { pageSize } : {},
218
+ ...sections.length > 0 ? { sections } : {},
137
219
  encrypted: false
138
220
  };
139
221
  }
222
+ function readFonts(wd, table) {
223
+ const fonts = [];
224
+ const fc = u32(wd, OFF_FCSTTBFFFN);
225
+ const lcb = u32(wd, OFF_LCBSTTBFFFN);
226
+ if (lcb < 4 || fc + lcb > table.length) return fonts;
227
+ const sttb = table.subarray(fc, fc + lcb);
228
+ const count = u16(sttb, 0);
229
+ let p = 4;
230
+ for (let i = 0; i < count && p < sttb.length; i++) {
231
+ const end = Math.min(sttb.length, p + 1 + sttb[p]);
232
+ let name = "";
233
+ for (let q = p + 40; q + 1 < end; q += 2) {
234
+ const c = u16(sttb, q);
235
+ if (c === 0) break;
236
+ name += String.fromCharCode(c);
237
+ }
238
+ fonts.push(name);
239
+ p = end;
240
+ }
241
+ return fonts;
242
+ }
243
+ function parseStyles(wd, table, fonts) {
244
+ const fc = u32(wd, OFF_FCSTSHF);
245
+ const lcb = u32(wd, OFF_LCBSTSHF);
246
+ if (lcb < 6 || fc + lcb > table.length) return void 0;
247
+ const stsh = table.subarray(fc, fc + lcb);
248
+ const cbStshi = u16(stsh, 0);
249
+ if (cbStshi < 4 || 2 + cbStshi > stsh.length) return void 0;
250
+ const cstd = u16(stsh, 2);
251
+ const cbStdBase = u16(stsh, 4);
252
+ const font = (key, off) => {
253
+ const name = cbStshi >= off ? fonts[u16(stsh, off)] : void 0;
254
+ return name ? { [key]: name } : {};
255
+ };
256
+ const defaults = {
257
+ ...font("fontAscii", 14),
258
+ ...font("fontEastAsia", 16),
259
+ ...font("fontOther", 18),
260
+ ...font("fontBi", 20)
261
+ };
262
+ const stds = [];
263
+ let p = 2 + cbStshi;
264
+ for (let istd = 0; istd < cstd && p + 2 <= stsh.length; istd++) {
265
+ const cbStd = u16(stsh, p);
266
+ p += 2;
267
+ stds.push(cbStd > 0 && p + cbStd <= stsh.length ? parseStd(stsh.subarray(p, p + cbStd), cbStdBase) : void 0);
268
+ p += cbStd;
269
+ }
270
+ const none = {
271
+ para: {},
272
+ chars: defaults
273
+ };
274
+ const memo = /* @__PURE__ */ new Map();
275
+ const paragraph = (istd, depth = 0) => {
276
+ const hit = memo.get(istd);
277
+ if (hit) return hit;
278
+ const std = stds[istd];
279
+ let out;
280
+ if (depth >= MAX_STYLE_DEPTH) out = none;
281
+ else if (std?.stk !== STK_PARAGRAPH) out = istd !== 0 ? paragraph(0, depth + 1) : none;
282
+ else {
283
+ const base = std.base !== ISTD_NIL && std.base !== istd ? paragraph(std.base, depth + 1) : none;
284
+ out = {
285
+ para: std.papx ? {
286
+ ...base.para,
287
+ ...decodePapxGrpprl(std.papx)
288
+ } : base.para,
289
+ chars: std.chpx ? {
290
+ ...base.chars,
291
+ ...decodeChpxGrpprl(std.chpx, base.chars, fonts)
292
+ } : base.chars
293
+ };
294
+ }
295
+ memo.set(istd, out);
296
+ return out;
297
+ };
298
+ const character = (istd, under, depth = 0) => {
299
+ const std = stds[istd];
300
+ if (std?.stk !== STK_CHARACTER || depth >= MAX_STYLE_DEPTH) return under;
301
+ const base = std.base !== ISTD_NIL && std.base !== istd ? character(std.base, under, depth + 1) : under;
302
+ return std.chpx ? {
303
+ ...base,
304
+ ...decodeChpxGrpprl(std.chpx, base, fonts)
305
+ } : base;
306
+ };
307
+ return {
308
+ paragraph: (istd) => paragraph(istd),
309
+ character: (istd, base) => character(istd, base)
310
+ };
311
+ }
312
+ function parseStd(std, cbStdBase) {
313
+ if (std.length < 6) return void 0;
314
+ const stk = u16(std, 2) & 15;
315
+ const base = u16(std, 2) >> 4;
316
+ const cupx = u16(std, 4) & 15;
317
+ let q = cbStdBase;
318
+ if (q + 2 > std.length) return {
319
+ stk,
320
+ base
321
+ };
322
+ q += 2 + u16(std, q) * 2 + 2;
323
+ const upx = [];
324
+ for (let k = 0; k < cupx && q + 2 <= std.length; k++) {
325
+ const cb = u16(std, q);
326
+ q += 2;
327
+ if (q + cb > std.length) break;
328
+ upx.push(std.subarray(q, q + cb));
329
+ q += cb + (cb & 1);
330
+ }
331
+ if (stk === STK_PARAGRAPH) {
332
+ const papx = upx[0] && upx[0].length >= 2 ? upx[0].subarray(2) : void 0;
333
+ return {
334
+ stk,
335
+ base,
336
+ ...papx ? { papx } : {},
337
+ ...upx[1] ? { chpx: upx[1] } : {}
338
+ };
339
+ }
340
+ if (stk === STK_CHARACTER) return {
341
+ stk,
342
+ base,
343
+ ...upx[0] ? { chpx: upx[0] } : {}
344
+ };
345
+ return {
346
+ stk,
347
+ base
348
+ };
349
+ }
350
+ function charStyleOf(grpprl) {
351
+ let istd;
352
+ for (const s of sprms(grpprl)) if (s.sprm === SPRM_C_ISTD) istd = u16(grpprl, s.op);
353
+ return istd;
354
+ }
140
355
  function parseListTables(wd, table) {
141
356
  const lstFc = u32(wd, OFF_FCPLFLST);
142
357
  const lstLcb = u32(wd, OFF_LCBPLFLST);
@@ -184,6 +399,7 @@ function readLvl(d, off) {
184
399
  if (off + 28 > d.length) return void 0;
185
400
  const iStartAt = u32(d, off) | 0;
186
401
  const nfc = d[off + 4];
402
+ const follow = d[off + 15];
187
403
  const cbChpx = d[off + 24];
188
404
  const cbPapx = d[off + 25];
189
405
  let p = off + 28 + cbPapx + cbChpx;
@@ -199,7 +415,8 @@ function readLvl(d, off) {
199
415
  info: {
200
416
  nfc,
201
417
  iStartAt,
202
- xst
418
+ xst,
419
+ follow
203
420
  },
204
421
  next: p
205
422
  };
@@ -259,7 +476,7 @@ function colorHex(r, g, b) {
259
476
  b
260
477
  ].map((c) => c.toString(16).padStart(2, "0")).join("").toUpperCase();
261
478
  }
262
- function extractHeaderFooters(wd, table, pieces, chpx, papx, data, ccpText) {
479
+ function extractHeaderFooters(wd, table, pieces, chpx, papx, data, ccpText, sectionCount, styles, fonts) {
263
480
  if (u32(wd, OFF_CCPHDD) === 0) return void 0;
264
481
  const fc = u32(wd, OFF_FCPLCFHDD);
265
482
  const lcb = u32(wd, OFF_LCBPLCFHDD);
@@ -268,28 +485,36 @@ function extractHeaderFooters(wd, table, pieces, chpx, papx, data, ccpText) {
268
485
  const n = Math.floor(lcb / 4);
269
486
  const hddStart = ccpText + u32(wd, OFF_CCPFTN);
270
487
  const story = (i) => {
271
- if (i + 1 >= n) return void 0;
488
+ if (i + 1 >= n) return "inherit";
272
489
  const a = hddStart + u32(plc, i * 4);
273
490
  const b = hddStart + u32(plc, (i + 1) * 4);
274
- if (b <= a) return void 0;
275
- const paras = buildParagraphs(wd, pieces, chpx, papx, a, b, data);
491
+ if (b <= a) return "inherit";
492
+ const paras = buildParagraphs(wd, pieces, chpx, papx, a, b, data, void 0, styles, fonts);
493
+ const last = paras[paras.length - 1];
494
+ if (last && last.runs.length === 0) paras.pop();
276
495
  return paras.some((p) => p.runs.some((r) => r.text.length > 0 || r.picture)) ? paras : void 0;
277
496
  };
278
- const evenHeader = story(6);
279
- const defaultHeader = story(7);
280
- const evenFooter = story(8);
281
- const defaultFooter = story(9);
282
- const firstHeader = story(10);
283
- const firstFooter = story(11);
284
- const hf = {
285
- ...defaultHeader ? { defaultHeader } : {},
286
- ...defaultFooter ? { defaultFooter } : {},
287
- ...firstHeader ? { firstHeader } : {},
288
- ...firstFooter ? { firstFooter } : {},
289
- ...evenHeader ? { evenHeader } : {},
290
- ...evenFooter ? { evenFooter } : {}
291
- };
292
- return Object.keys(hf).length > 0 ? hf : void 0;
497
+ const SLOTS = [
498
+ "evenHeader",
499
+ "defaultHeader",
500
+ "evenFooter",
501
+ "defaultFooter",
502
+ "firstHeader",
503
+ "firstFooter"
504
+ ];
505
+ const out = [];
506
+ let prev = {};
507
+ for (let sec = 0; sec < sectionCount; sec++) {
508
+ const hf = {};
509
+ SLOTS.forEach((slot, k) => {
510
+ const got = story(6 + sec * 6 + k);
511
+ const paras = got === "inherit" ? prev[slot] : got;
512
+ if (paras) hf[slot] = paras;
513
+ });
514
+ out.push(hf);
515
+ prev = hf;
516
+ }
517
+ return out.some((hf) => Object.keys(hf).length > 0) ? out : void 0;
293
518
  }
294
519
  function findPlcPcd(clx) {
295
520
  let p = 0;
@@ -342,24 +567,32 @@ function parsePlcBte(wd, table, fcOff, lcbOff, parsePage) {
342
567
  out.sort((a, b) => a.fcStart - b.fcStart);
343
568
  return out;
344
569
  }
345
- function parseChpxFkp(page, out) {
570
+ function parseChpxFkp(page, out, fonts) {
346
571
  const crun = page[511];
347
572
  if (crun === 0 || (crun + 1) * 4 + crun > 511) return;
348
573
  for (let i = 0; i < crun; i++) {
349
574
  const fcStart = u32(page, i * 4);
350
575
  const fcEnd = u32(page, (i + 1) * 4);
351
576
  if (fcEnd <= fcStart) continue;
352
- let props = {};
353
577
  const wordOff = page[(crun + 1) * 4 + i];
354
578
  if (wordOff !== 0) {
355
579
  const chpxOff = wordOff * 2;
356
580
  const cb = chpxOff < FKP_SIZE ? page[chpxOff] : 0;
357
- if (cb > 0 && chpxOff + 1 + cb <= FKP_SIZE) props = decodeChpxGrpprl(page.subarray(chpxOff + 1, chpxOff + 1 + cb));
581
+ if (cb > 0 && chpxOff + 1 + cb <= FKP_SIZE) {
582
+ const grpprl = page.subarray(chpxOff + 1, chpxOff + 1 + cb);
583
+ out.push({
584
+ fcStart,
585
+ fcEnd,
586
+ props: decodeChpxGrpprl(grpprl, {}, fonts),
587
+ grpprl
588
+ });
589
+ continue;
590
+ }
358
591
  }
359
592
  out.push({
360
593
  fcStart,
361
594
  fcEnd,
362
- props
595
+ props: {}
363
596
  });
364
597
  }
365
598
  }
@@ -371,34 +604,49 @@ function parsePapxFkp(page, out) {
371
604
  const fcStart = u32(page, i * 4);
372
605
  const fcEnd = u32(page, (i + 1) * 4);
373
606
  if (fcEnd <= fcStart) continue;
374
- let props = {};
375
607
  const papxOff = page[bxBase + i * 13] * 2;
376
608
  if (papxOff !== 0 && papxOff < FKP_SIZE) {
377
609
  const cb = page[papxOff];
378
610
  const size = cb !== 0 ? 2 * cb - 1 : 2 * (page[papxOff + 1] ?? 0);
379
611
  const start = cb !== 0 ? papxOff + 1 : papxOff + 2;
380
- if (size >= 2 && start + size <= FKP_SIZE) props = decodePapxGrpprl(page.subarray(start + 2, start + size));
612
+ if (size >= 2 && start + size <= FKP_SIZE) {
613
+ const grpprl = page.subarray(start + 2, start + size);
614
+ const istd = u16(page, start);
615
+ out.push({
616
+ fcStart,
617
+ fcEnd,
618
+ props: decodePapxGrpprl(grpprl),
619
+ grpprl,
620
+ istd
621
+ });
622
+ continue;
623
+ }
381
624
  }
382
625
  out.push({
383
626
  fcStart,
384
627
  fcEnd,
385
- props
628
+ props: {}
386
629
  });
387
630
  }
388
631
  }
389
- function decodeChpxGrpprl(d) {
632
+ function decodeChpxGrpprl(d, style = {}, fonts = []) {
390
633
  let bold;
391
634
  let italic;
392
635
  let underlineKul;
393
636
  let sizeHalfPts;
394
637
  let fSpec;
395
638
  let picOffset;
639
+ const named = {};
640
+ const font = (key, ftc) => {
641
+ const name = fonts[ftc];
642
+ if (name) named[key] = name;
643
+ };
396
644
  for (const s of sprms(d)) switch (s.sprm) {
397
645
  case SPRM_C_FBOLD:
398
- bold = toggleBool(d[s.op]);
646
+ bold = toggleBool(d[s.op], style.bold);
399
647
  break;
400
648
  case SPRM_C_FITALIC:
401
- italic = toggleBool(d[s.op]);
649
+ italic = toggleBool(d[s.op], style.italic);
402
650
  break;
403
651
  case SPRM_C_KUL:
404
652
  underlineKul = d[s.op];
@@ -406,6 +654,18 @@ function decodeChpxGrpprl(d) {
406
654
  case SPRM_C_HPS:
407
655
  sizeHalfPts = u16(d, s.op);
408
656
  break;
657
+ case SPRM_C_RG_FTC0:
658
+ font("fontAscii", u16(d, s.op));
659
+ break;
660
+ case SPRM_C_RG_FTC1:
661
+ font("fontEastAsia", u16(d, s.op));
662
+ break;
663
+ case SPRM_C_RG_FTC2:
664
+ font("fontOther", u16(d, s.op));
665
+ break;
666
+ case SPRM_C_FTC_BI:
667
+ font("fontBi", u16(d, s.op));
668
+ break;
409
669
  case SPRM_C_FSPEC:
410
670
  fSpec = d[s.op] !== 0;
411
671
  break;
@@ -416,6 +676,7 @@ function decodeChpxGrpprl(d) {
416
676
  ...italic !== void 0 ? { italic } : {},
417
677
  ...underlineKul !== void 0 ? { underlineKul } : {},
418
678
  ...sizeHalfPts !== void 0 ? { sizeHalfPts } : {},
679
+ ...named,
419
680
  ...fSpec ? { fSpec } : {},
420
681
  ...picOffset !== void 0 ? { picOffset } : {}
421
682
  };
@@ -437,6 +698,7 @@ function decodePapxGrpprl(d) {
437
698
  let widowControl;
438
699
  let keepNext;
439
700
  let keepLines;
701
+ let pageBreakBefore;
440
702
  for (const s of sprms(d)) switch (s.sprm) {
441
703
  case SPRM_P_JC:
442
704
  jc = d[s.op];
@@ -471,6 +733,9 @@ function decodePapxGrpprl(d) {
471
733
  case SPRM_P_F_KEEP:
472
734
  keepLines = d[s.op] !== 0;
473
735
  break;
736
+ case SPRM_P_F_PAGE_BREAK_BEFORE:
737
+ pageBreakBefore = d[s.op] !== 0;
738
+ break;
474
739
  case SPRM_T_DEF_TABLE: {
475
740
  const cols = d[s.op] ?? 0;
476
741
  const edges = [];
@@ -483,7 +748,7 @@ function decodePapxGrpprl(d) {
483
748
  break;
484
749
  }
485
750
  case SPRM_P_ILVL:
486
- listIlvl = d[s.op];
751
+ listIlvl = d[s.op] <= 8 ? d[s.op] : 0;
487
752
  break;
488
753
  case SPRM_T_DEF_TABLE_SHD: {
489
754
  const shd = [];
@@ -512,7 +777,8 @@ function decodePapxGrpprl(d) {
512
777
  ...listIlvl !== void 0 ? { listIlvl } : {},
513
778
  ...widowControl !== void 0 ? { widowControl } : {},
514
779
  ...keepNext !== void 0 ? { keepNext } : {},
515
- ...keepLines !== void 0 ? { keepLines } : {}
780
+ ...keepLines !== void 0 ? { keepLines } : {},
781
+ ...pageBreakBefore !== void 0 ? { pageBreakBefore } : {}
516
782
  };
517
783
  }
518
784
  function* sprms(d) {
@@ -544,9 +810,11 @@ function* sprms(d) {
544
810
  p = op + len;
545
811
  }
546
812
  }
547
- function toggleBool(v) {
813
+ function toggleBool(v, style) {
548
814
  if (v === 0) return false;
549
- if (v === 1 || v === 129) return true;
815
+ if (v === 1) return true;
816
+ if (v === 128) return style;
817
+ if (v === 129) return style !== true;
550
818
  }
551
819
  function extractPicture(data, fcPic) {
552
820
  if (fcPic < 0 || fcPic + 36 > data.length) return void 0;
@@ -605,32 +873,71 @@ function magicAt(d, off, magic) {
605
873
  for (let i = 0; i < magic.length; i++) if (d[off + i] !== magic[i]) return false;
606
874
  return true;
607
875
  }
608
- function buildParagraphs(wd, pieces, chpx, papx, cpStart, cpEnd, data) {
876
+ function buildParagraphs(wd, pieces, chpx, papx, cpStart, cpEnd, data, sectionEnds = /* @__PURE__ */ new Map(), styles, fonts = []) {
609
877
  const end = Math.min(cpEnd, cpStart + MAX_TEXT);
610
878
  const paragraphs = [];
611
879
  let runs = [];
880
+ let chpxOf = [];
612
881
  let cur = "";
613
- let curProps = {};
882
+ let curChpx;
614
883
  let lastFc = 0;
615
884
  let fieldDepth = 0;
616
885
  let codeDepth = 0;
886
+ let instr = "";
887
+ let page;
888
+ const push = (run, from) => {
889
+ runs.push(run);
890
+ chpxOf.push(from);
891
+ };
617
892
  const flushRun = () => {
618
893
  if (cur.length > 0) {
619
- runs.push({
894
+ push({
620
895
  text: cur,
621
- props: curProps
622
- });
896
+ props: curChpx?.props ?? {}
897
+ }, curChpx);
623
898
  cur = "";
624
899
  }
625
900
  };
626
- const endParagraph = (fc, cellMark) => {
901
+ const runProps = (from, base) => {
902
+ if (!from?.grpprl) return base;
903
+ const cistd = charStyleOf(from.grpprl);
904
+ const under = cistd !== void 0 && styles ? styles.character(cistd, base) : base;
905
+ return {
906
+ ...under,
907
+ ...decodeChpxGrpprl(from.grpprl, under, fonts)
908
+ };
909
+ };
910
+ const endParagraph = (fc, cellMark, sectionEnd) => {
627
911
  flushRun();
912
+ const pap = lookupRun(papx, fc);
913
+ const style = styles?.paragraph(pap?.istd ?? 0);
914
+ const settled = [];
915
+ runs.forEach((run, i) => {
916
+ const props = style && !run.picture ? runProps(chpxOf[i], style.chars) : run.props;
917
+ const prev = settled[settled.length - 1];
918
+ if (prev && plainText(prev) && plainText(run) && sameProps(prev.props, props)) settled[settled.length - 1] = {
919
+ text: prev.text + run.text,
920
+ props: prev.props
921
+ };
922
+ else settled.push({
923
+ ...run,
924
+ props
925
+ });
926
+ });
927
+ const markChpx = lookupRun(chpx, fc);
928
+ const mark = style ? runProps(markChpx, style.chars) : markChpx?.props;
628
929
  paragraphs.push({
629
- runs,
630
- props: lookup(papx, fc) ?? {},
631
- ...cellMark ? { cellMark: true } : {}
930
+ runs: settled,
931
+ props: style ? {
932
+ ...style.para,
933
+ ...pap?.props ?? {}
934
+ } : pap?.props ?? {},
935
+ ...cellMark ? { cellMark: true } : {},
936
+ ...sectionEnd !== void 0 ? { sectionEnd } : {},
937
+ ...mark && Object.keys(mark).length > 0 ? { mark } : {}
632
938
  });
633
939
  runs = [];
940
+ chpxOf = [];
634
941
  };
635
942
  for (const piece of pieces) {
636
943
  if (piece.cpStart >= end) break;
@@ -643,45 +950,91 @@ function buildParagraphs(wd, pieces, chpx, papx, cpStart, cpEnd, data) {
643
950
  lastFc = fc;
644
951
  const code = piece.compressed ? byteCode(wd, fc) : unitCode(wd, fc);
645
952
  if (code < 0) continue;
646
- if (code === CR || code === CELL_MARK) {
647
- endParagraph(fc, code === CELL_MARK);
953
+ const sectionEnd = code === PAGE_BREAK ? sectionEnds.get(piece.cpStart + k + 1) : void 0;
954
+ if (code === CR || code === CELL_MARK || sectionEnd !== void 0) {
955
+ endParagraph(fc, code === CELL_MARK, sectionEnd);
648
956
  continue;
649
957
  }
650
958
  if (code === FIELD_BEGIN) {
959
+ if (codeDepth === 0) instr = "";
651
960
  fieldDepth++;
652
961
  codeDepth++;
653
962
  continue;
654
963
  }
655
964
  if (code === FIELD_SEPARATOR) {
656
- if (codeDepth > 0) codeDepth--;
965
+ const ended = codeDepth > 0;
966
+ if (ended) codeDepth--;
967
+ const field = ended && codeDepth === 0 && !page ? pageField(instr) : void 0;
968
+ if (field) {
969
+ flushRun();
970
+ const sep = lookupRun(chpx, fc);
971
+ page = {
972
+ field,
973
+ depth: fieldDepth,
974
+ paragraph: paragraphs.length,
975
+ at: runs.length,
976
+ ...sep ? { sep } : {}
977
+ };
978
+ }
657
979
  continue;
658
980
  }
659
981
  if (code === FIELD_END) {
982
+ if (page?.depth === fieldDepth) {
983
+ if (page.paragraph === paragraphs.length) {
984
+ flushRun();
985
+ const result = runs.splice(page.at);
986
+ const from = chpxOf.splice(page.at)[0] ?? page.sep;
987
+ push({
988
+ text: result.map((r) => r.text).join(""),
989
+ props: from?.props ?? {},
990
+ field: page.field
991
+ }, from);
992
+ }
993
+ page = void 0;
994
+ }
660
995
  if (fieldDepth > 0) fieldDepth--;
661
996
  if (codeDepth > fieldDepth) codeDepth = fieldDepth;
662
997
  continue;
663
998
  }
664
- if (codeDepth > 0) continue;
999
+ if (codeDepth > 0) {
1000
+ if (codeDepth === 1 && instr.length < MAX_FIELD_INSTR) instr += String.fromCharCode(code);
1001
+ continue;
1002
+ }
665
1003
  if (code === PIC_CHAR) {
666
1004
  const props = lookup(chpx, fc) ?? {};
667
1005
  const picture = data && props.fSpec && props.picOffset !== void 0 ? extractPicture(data, props.picOffset) : void 0;
668
1006
  if (picture) {
669
1007
  flushRun();
670
- runs.push({
1008
+ push({
671
1009
  text: "",
672
1010
  props: {},
673
1011
  picture
674
- });
1012
+ }, void 0);
675
1013
  }
676
1014
  continue;
677
1015
  }
678
- const ch = code === 9 || code === 11 ? " " : code < 32 ? "" : String.fromCharCode(code);
1016
+ if (code === PAGE_BREAK || code === COLUMN_BREAK) {
1017
+ flushRun();
1018
+ const from = lookupRun(chpx, fc);
1019
+ const props = from?.props ?? {};
1020
+ push(code === PAGE_BREAK ? {
1021
+ text: "",
1022
+ props,
1023
+ pageBreak: true
1024
+ } : {
1025
+ text: "\n",
1026
+ props,
1027
+ columnBreak: true
1028
+ }, from);
1029
+ continue;
1030
+ }
1031
+ const ch = code === LINE_BREAK ? "\n" : code === 9 ? " " : code < 32 ? "" : String.fromCharCode(code);
679
1032
  if (ch.length === 0) continue;
680
- const props = lookup(chpx, fc) ?? {};
681
- if (cur.length === 0) curProps = props;
682
- else if (!sameProps(props, curProps)) {
1033
+ const from = lookupRun(chpx, fc);
1034
+ if (cur.length === 0) curChpx = from;
1035
+ else if (from !== curChpx) {
683
1036
  flushRun();
684
- curProps = props;
1037
+ curChpx = from;
685
1038
  }
686
1039
  cur += ch;
687
1040
  }
@@ -690,6 +1043,9 @@ function buildParagraphs(wd, pieces, chpx, papx, cpStart, cpEnd, data) {
690
1043
  return paragraphs;
691
1044
  }
692
1045
  function lookup(runs, fc) {
1046
+ return lookupRun(runs, fc)?.props;
1047
+ }
1048
+ function lookupRun(runs, fc) {
693
1049
  let lo = 0;
694
1050
  let hi = runs.length - 1;
695
1051
  while (lo <= hi) {
@@ -697,11 +1053,18 @@ function lookup(runs, fc) {
697
1053
  const r = runs[mid];
698
1054
  if (fc < r.fcStart) hi = mid - 1;
699
1055
  else if (fc >= r.fcEnd) lo = mid + 1;
700
- else return r.props;
1056
+ else return r;
701
1057
  }
702
1058
  }
1059
+ function plainText(run) {
1060
+ return !run.picture && !run.pageBreak && !run.columnBreak && !run.field;
1061
+ }
1062
+ function pageField(code) {
1063
+ const keyword = /^\s*([A-Za-z]+)/.exec(code)?.[1]?.toUpperCase();
1064
+ return keyword === "PAGE" || keyword === "NUMPAGES" ? keyword : void 0;
1065
+ }
703
1066
  function sameProps(a, b) {
704
- return a.bold === b.bold && a.italic === b.italic && a.underlineKul === b.underlineKul && a.sizeHalfPts === b.sizeHalfPts;
1067
+ return a.bold === b.bold && a.italic === b.italic && a.underlineKul === b.underlineKul && a.sizeHalfPts === b.sizeHalfPts && a.fontAscii === b.fontAscii && a.fontEastAsia === b.fontEastAsia && a.fontOther === b.fontOther && a.fontBi === b.fontBi;
705
1068
  }
706
1069
  var CP1252_HIGH = [
707
1070
  8364,