js.documents 1.102.2 → 2.0.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 (40) hide show
  1. package/README.md +8 -5
  2. package/dist/convert/composition.cjs +15 -4
  3. package/dist/convert/composition.js +15 -4
  4. package/dist/convert/convert.cjs +6 -3
  5. package/dist/convert/convert.js +6 -3
  6. package/dist/convert/from-package.cjs +179 -2
  7. package/dist/convert/from-package.d.cts +3 -2
  8. package/dist/convert/from-package.d.ts +3 -2
  9. package/dist/convert/from-package.js +179 -3
  10. package/dist/index.cjs +1 -0
  11. package/dist/index.d.cts +3 -3
  12. package/dist/index.d.ts +3 -3
  13. package/dist/index.js +2 -2
  14. package/dist/layout/drawing.cjs +71 -9
  15. package/dist/layout/drawing.d.cts +8 -3
  16. package/dist/layout/drawing.d.ts +8 -3
  17. package/dist/layout/drawing.js +71 -10
  18. package/dist/layout/engine.cjs +55 -43
  19. package/dist/layout/engine.d.cts +2 -1
  20. package/dist/layout/engine.d.ts +2 -1
  21. package/dist/layout/engine.js +57 -45
  22. package/dist/layout/reconstruct.cjs +259 -104
  23. package/dist/layout/reconstruct.js +259 -104
  24. package/dist/layout/shared.cjs +47 -2
  25. package/dist/layout/shared.d.cts +15 -4
  26. package/dist/layout/shared.d.ts +15 -4
  27. package/dist/layout/shared.js +44 -4
  28. package/dist/layout/sheets.cjs +18 -13
  29. package/dist/layout/sheets.d.cts +4 -2
  30. package/dist/layout/sheets.d.ts +4 -2
  31. package/dist/layout/sheets.js +20 -16
  32. package/dist/layout/slides.cjs +35 -31
  33. package/dist/layout/slides.d.cts +3 -2
  34. package/dist/layout/slides.d.ts +3 -2
  35. package/dist/layout/slides.js +37 -33
  36. package/dist/layout/text-layout.cjs +2 -1
  37. package/dist/layout/text-layout.d.cts +14 -3
  38. package/dist/layout/text-layout.d.ts +14 -3
  39. package/dist/layout/text-layout.js +2 -1
  40. package/package.json +5 -5
@@ -1,5 +1,6 @@
1
1
  import { flipY } from "../model/geometry.js";
2
2
  import { buildDrawingBlock } from "../model/embedded-drawing.js";
3
+ import { stampFrame } from "./shared.js";
3
4
  import { throwIfAborted } from "../ports/abort.js";
4
5
  import { inferCellValue } from "./cell-typing.js";
5
6
  import { detectGridLattice, findColumnIndex, findRowIndex } from "./lattice.js";
@@ -48,7 +49,37 @@ function textItemToContentRun(item) {
48
49
  };
49
50
  }
50
51
  const MIN_WORD_GAP_PT = .5;
51
- function pushRunsForLine(runs, line) {
52
+ function textBoxOfItem(item, pageIndex) {
53
+ const { ascentPt, descentPt } = textItemVerticalExtent(item);
54
+ return {
55
+ pageIndex,
56
+ xPt: item.xPt,
57
+ yPt: item.yPt - descentPt,
58
+ widthPt: item.widthPt ?? 0,
59
+ heightPt: ascentPt + descentPt
60
+ };
61
+ }
62
+ function lineBox(line, pageIndex) {
63
+ let minX = Number.POSITIVE_INFINITY;
64
+ let maxX = Number.NEGATIVE_INFINITY;
65
+ let minY = Number.POSITIVE_INFINITY;
66
+ let maxY = Number.NEGATIVE_INFINITY;
67
+ for (const item of line.items) {
68
+ const { ascentPt, descentPt } = textItemVerticalExtent(item);
69
+ minX = Math.min(minX, item.xPt);
70
+ maxX = Math.max(maxX, item.xPt + (item.widthPt ?? 0));
71
+ minY = Math.min(minY, item.yPt - descentPt);
72
+ maxY = Math.max(maxY, item.yPt + ascentPt);
73
+ }
74
+ return {
75
+ pageIndex,
76
+ xPt: minX,
77
+ yPt: minY,
78
+ widthPt: maxX - minX,
79
+ heightPt: maxY - minY
80
+ };
81
+ }
82
+ function pushRunsForLine(runs, line, pageIndex) {
52
83
  line.items.forEach((item, itemIndex) => {
53
84
  if (itemIndex > 0) {
54
85
  const prevItem = line.items[itemIndex - 1];
@@ -56,7 +87,9 @@ function pushRunsForLine(runs, line) {
56
87
  if (gap > LARGE_GAP_EM_MULTIPLIER * item.sizePt) runs.push({ text: " " });
57
88
  else if (gap > MIN_WORD_GAP_PT) runs[runs.length - 1].text += " ";
58
89
  }
59
- runs.push(textItemToContentRun(item));
90
+ const run = textItemToContentRun(item);
91
+ stampFrame(run, pageIndex, textBoxOfItem(item, pageIndex));
92
+ runs.push(run);
60
93
  });
61
94
  }
62
95
  function bucketCounts(values, bucketSize) {
@@ -102,15 +135,17 @@ function reconstructWordprocessing(doc, options) {
102
135
  const signal = options?.signal;
103
136
  const sections = [];
104
137
  let currentGroup = [];
138
+ let groupStartPageIndex = 0;
105
139
  for (const page of doc.pages) {
106
140
  throwIfAborted(signal);
107
141
  if (currentGroup.length > 0 && !samePageSize(currentGroup[0], page)) {
108
- sections.push(buildSection(currentGroup, doc.images));
142
+ sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images));
143
+ groupStartPageIndex += currentGroup.length;
109
144
  currentGroup = [];
110
145
  }
111
146
  currentGroup.push(page);
112
147
  }
113
- if (currentGroup.length > 0) sections.push(buildSection(currentGroup, doc.images));
148
+ if (currentGroup.length > 0) sections.push(buildSection(currentGroup, groupStartPageIndex, doc.images));
114
149
  return {
115
150
  kind: "wordprocessing",
116
151
  formatVersion: CONTENT_FORMAT_VERSION,
@@ -121,11 +156,11 @@ function reconstructWordprocessing(doc, options) {
121
156
  function samePageSize(a, b) {
122
157
  return a.widthPt === b.widthPt && a.heightPt === b.heightPt;
123
158
  }
124
- function buildSection(pages, images) {
159
+ function buildSection(pages, startPageIndex, images) {
125
160
  const blocks = [];
126
161
  pages.forEach((page, i) => {
127
162
  if (i > 0) blocks.push({ kind: "pageBreak" });
128
- blocks.push(...reconstructPageBlocks(page, images));
163
+ blocks.push(...reconstructPageBlocks(page, startPageIndex + i, images));
129
164
  });
130
165
  return {
131
166
  pageSize: {
@@ -136,8 +171,8 @@ function buildSection(pages, images) {
136
171
  blocks
137
172
  };
138
173
  }
139
- function reconstructPageBlocks(page, images) {
140
- const recoveredTable = recoverTable(page);
174
+ function reconstructPageBlocks(page, pageIndex, images) {
175
+ const recoveredTable = recoverTable(page, pageIndex);
141
176
  const consumedText = recoveredTable?.consumedText;
142
177
  const textItems = page.items.filter((i) => i.kind === "text" && consumedText?.has(i) !== true);
143
178
  const imageItems = page.items.filter((i) => i.kind === "image");
@@ -145,26 +180,35 @@ function reconstructPageBlocks(page, images) {
145
180
  const positioned = [];
146
181
  for (const paragraph of paragraphs) positioned.push({
147
182
  yPt: paragraph.lines[0].baselineY,
148
- block: paragraphToContentParagraph(paragraph)
183
+ block: paragraphToContentParagraph(paragraph, pageIndex)
149
184
  });
150
185
  for (const img of imageItems) {
151
186
  const asset = images[img.imageId];
152
- if (asset !== void 0) positioned.push({
153
- yPt: img.yPt,
154
- block: {
187
+ if (asset !== void 0) {
188
+ const block = {
155
189
  kind: "image",
156
190
  format: asset.format,
157
191
  base64: asset.base64,
158
192
  widthPt: img.widthPt,
159
193
  heightPt: img.heightPt
160
- }
161
- });
194
+ };
195
+ stampFrame(block, pageIndex, {
196
+ xPt: img.xPt,
197
+ yPt: img.yPt,
198
+ widthPt: img.widthPt,
199
+ heightPt: img.heightPt
200
+ });
201
+ positioned.push({
202
+ yPt: img.yPt,
203
+ block
204
+ });
205
+ }
162
206
  }
163
207
  if (recoveredTable !== void 0) positioned.push({
164
208
  yPt: recoveredTable.topYPt,
165
209
  block: recoveredTable.table
166
210
  });
167
- const recoveredVectors = recoverPageVectors(page, recoveredTable?.latticeItems ?? NO_ITEMS);
211
+ const recoveredVectors = recoverPageVectors(page, pageIndex, recoveredTable?.latticeItems ?? NO_ITEMS);
168
212
  if (recoveredVectors !== void 0) positioned.push({
169
213
  yPt: recoveredVectors.topYPt,
170
214
  block: recoveredVectors.block
@@ -195,28 +239,28 @@ function startsNewParagraph(prev, next, modalSpacing, dominantLeftX) {
195
239
  return nextIndented && prevAtMargin;
196
240
  }
197
241
  const LEFT_ALIGN_TOLERANCE_PT = 2;
198
- function paragraphToContentParagraph(paragraph) {
242
+ function paragraphToContentParagraph(paragraph, pageIndex) {
199
243
  const dominantLeftX = modeOf(paragraph.lines.map((l) => l.items[0].xPt), 1);
200
- const alignment = paragraph.lines.every((l) => Math.abs(l.items[0].xPt - dominantLeftX) <= LEFT_ALIGN_TOLERANCE_PT) ? "left" : void 0;
201
- const runs = [];
244
+ const result = {
245
+ kind: "paragraph",
246
+ runs: [],
247
+ alignment: paragraph.lines.every((l) => Math.abs(l.items[0].xPt - dominantLeftX) <= LEFT_ALIGN_TOLERANCE_PT) ? "left" : void 0
248
+ };
202
249
  paragraph.lines.forEach((line, lineIndex) => {
250
+ stampFrame(result, pageIndex, lineBox(line, pageIndex));
203
251
  if (lineIndex > 0) {
204
- const lastRun = runs[runs.length - 1];
252
+ const lastRun = result.runs[result.runs.length - 1];
205
253
  if (lastRun !== void 0) lastRun.text += " ";
206
254
  }
207
- pushRunsForLine(runs, line);
255
+ pushRunsForLine(result.runs, line, pageIndex);
208
256
  });
209
- return {
210
- kind: "paragraph",
211
- runs,
212
- alignment
213
- };
257
+ return result;
214
258
  }
215
259
  function reconstructPresentation(doc, options) {
216
260
  const signal = options?.signal;
217
- const slides = doc.pages.map((page) => {
261
+ const slides = doc.pages.map((page, pageIndex) => {
218
262
  throwIfAborted(signal);
219
- return reconstructSlide(page, doc.images);
263
+ return reconstructSlide(page, pageIndex, doc.images);
220
264
  });
221
265
  return {
222
266
  kind: "presentation",
@@ -225,25 +269,25 @@ function reconstructPresentation(doc, options) {
225
269
  slides
226
270
  };
227
271
  }
228
- function reconstructSlide(page, images) {
229
- const recoveredTable = recoverTable(page);
272
+ function reconstructSlide(page, pageIndex, images) {
273
+ const recoveredTable = recoverTable(page, pageIndex);
230
274
  const consumedText = recoveredTable?.consumedText;
231
275
  const textItems = page.items.filter((i) => i.kind === "text" && consumedText?.has(i) !== true);
232
276
  const imageItems = page.items.filter((i) => i.kind === "image");
233
- const textShapes = clusterIntoBlocks(clusterIntoLines(textItems)).map((block) => blockToShape(block, page.heightPt));
277
+ const textShapes = clusterIntoBlocks(clusterIntoLines(textItems)).map((block) => blockToShape(block, page.heightPt, pageIndex));
234
278
  const imageShapes = [];
235
279
  for (const img of imageItems) {
236
- const shape = imageToShape(img, page.heightPt, images);
280
+ const shape = imageToShape(img, page.heightPt, pageIndex, images);
237
281
  if (shape !== void 0) imageShapes.push(shape);
238
282
  }
239
- const recoveredVectors = recoverPageVectors(page, recoveredTable?.latticeItems ?? NO_ITEMS);
283
+ const recoveredVectors = recoverPageVectors(page, pageIndex, recoveredTable?.latticeItems ?? NO_ITEMS);
240
284
  const vectorShapes = recoveredVectors === void 0 ? [] : [wrapBlockInShape(recoveredVectors.block, {
241
285
  xPt: 0,
242
286
  yPt: 0,
243
287
  widthPt: page.widthPt,
244
288
  heightPt: page.heightPt
245
- })];
246
- const tableShapes = recoveredTable === void 0 ? [] : [wrapBlockInShape(recoveredTable.table, recoveredTable.frame)];
289
+ }, page.heightPt, pageIndex)];
290
+ const tableShapes = recoveredTable === void 0 ? [] : [wrapBlockInShape(recoveredTable.table, recoveredTable.frame, page.heightPt, pageIndex)];
247
291
  return {
248
292
  size: {
249
293
  widthPt: page.widthPt,
@@ -258,8 +302,8 @@ function reconstructSlide(page, images) {
258
302
  notes: page.notes ?? ""
259
303
  };
260
304
  }
261
- function wrapBlockInShape(block, frame) {
262
- return {
305
+ function wrapBlockInShape(block, frame, pageHeightPt, pageIndex) {
306
+ const shape = {
263
307
  frame,
264
308
  insetLeftPt: 0,
265
309
  insetTopPt: 0,
@@ -267,6 +311,8 @@ function wrapBlockInShape(block, frame) {
267
311
  insetBottomPt: 0,
268
312
  blocks: [block]
269
313
  };
314
+ stampFrame(shape, pageIndex, flipY(frame, pageHeightPt));
315
+ return shape;
270
316
  }
271
317
  function splitLineByLargeGaps(line) {
272
318
  const segments = [];
@@ -333,53 +379,71 @@ function computeBlockFrame(block, slideHeightPt) {
333
379
  heightPt: maxY - minY
334
380
  }, slideHeightPt);
335
381
  }
336
- function lineToParagraph(line) {
337
- const runs = [];
338
- pushRunsForLine(runs, line);
339
- return {
382
+ function lineToParagraph(line, pageIndex) {
383
+ const paragraph = {
340
384
  kind: "paragraph",
341
- runs
385
+ runs: []
342
386
  };
387
+ stampFrame(paragraph, pageIndex, lineBox(line, pageIndex));
388
+ pushRunsForLine(paragraph.runs, line, pageIndex);
389
+ return paragraph;
343
390
  }
344
- function blockToShape(block, slideHeightPt) {
345
- return {
391
+ function blockToShape(block, slideHeightPt, pageIndex) {
392
+ const shape = {
346
393
  frame: computeBlockFrame(block, slideHeightPt),
347
394
  insetLeftPt: 0,
348
395
  insetTopPt: 0,
349
396
  insetRightPt: 0,
350
397
  insetBottomPt: 0,
351
- blocks: block.lines.map(lineToParagraph)
398
+ blocks: block.lines.map((line) => lineToParagraph(line, pageIndex))
352
399
  };
400
+ stampFrame(shape, pageIndex, flipY(shape.frame, slideHeightPt));
401
+ return shape;
353
402
  }
354
- function imageToShape(img, slideHeightPt, images) {
403
+ function imageToShape(img, slideHeightPt, pageIndex, images) {
355
404
  const asset = images[img.imageId];
356
405
  if (asset === void 0) return;
357
- return {
358
- frame: flipY({
359
- xPt: img.xPt,
360
- yPt: img.yPt,
361
- widthPt: img.widthPt,
362
- heightPt: img.heightPt
363
- }, slideHeightPt),
406
+ const frame = flipY({
407
+ xPt: img.xPt,
408
+ yPt: img.yPt,
409
+ widthPt: img.widthPt,
410
+ heightPt: img.heightPt
411
+ }, slideHeightPt);
412
+ const block = {
413
+ kind: "image",
414
+ format: asset.format,
415
+ base64: asset.base64,
416
+ widthPt: img.widthPt,
417
+ heightPt: img.heightPt
418
+ };
419
+ stampFrame(block, pageIndex, {
420
+ xPt: img.xPt,
421
+ yPt: img.yPt,
422
+ widthPt: img.widthPt,
423
+ heightPt: img.heightPt
424
+ });
425
+ const shape = {
426
+ frame,
364
427
  rotationDeg: img.rotationDeg !== void 0 ? -img.rotationDeg : void 0,
365
428
  insetLeftPt: 0,
366
429
  insetTopPt: 0,
367
430
  insetRightPt: 0,
368
431
  insetBottomPt: 0,
369
- blocks: [{
370
- kind: "image",
371
- format: asset.format,
372
- base64: asset.base64,
373
- widthPt: img.widthPt,
374
- heightPt: img.heightPt
375
- }]
432
+ blocks: [block]
376
433
  };
434
+ stampFrame(shape, pageIndex, {
435
+ xPt: img.xPt,
436
+ yPt: img.yPt,
437
+ widthPt: img.widthPt,
438
+ heightPt: img.heightPt
439
+ });
440
+ return shape;
377
441
  }
378
442
  function reconstructDrawing(doc, options) {
379
443
  const signal = options?.signal;
380
- const pages = doc.pages.map((page) => {
444
+ const pages = doc.pages.map((page, pageIndex) => {
381
445
  throwIfAborted(signal);
382
- return reconstructDrawPage(page, doc.images);
446
+ return reconstructDrawPage(page, pageIndex, doc.images);
383
447
  });
384
448
  return {
385
449
  kind: "drawing",
@@ -388,25 +452,29 @@ function reconstructDrawing(doc, options) {
388
452
  pages
389
453
  };
390
454
  }
391
- function reconstructDrawPage(page, images) {
455
+ function reconstructDrawPage(page, pageIndex, images) {
392
456
  const vectors = [];
393
457
  const shapes = [];
394
458
  let paintOrder = 0;
395
459
  for (const item of page.items) {
396
460
  const vector = layoutItemToVector(item, page.heightPt);
397
461
  if (vector !== void 0) {
462
+ stampVectorFrame(vector, item, pageIndex);
398
463
  vectors.push({
399
464
  ...vector,
400
465
  paintOrder: paintOrder++
401
466
  });
402
467
  continue;
403
468
  }
404
- if (item.kind === "text") shapes.push({
405
- ...layoutTextToShape(item, page.heightPt),
406
- paintOrder: paintOrder++
407
- });
408
- else if (item.kind === "image") {
409
- const shape = imageToShape(item, page.heightPt, images);
469
+ if (item.kind === "text") {
470
+ const shape = layoutTextToShape(item, page.heightPt, pageIndex);
471
+ stampFrame(shape, pageIndex, flipY(shape.frame, page.heightPt));
472
+ shapes.push({
473
+ ...shape,
474
+ paintOrder: paintOrder++
475
+ });
476
+ } else if (item.kind === "image") {
477
+ const shape = imageToShape(item, page.heightPt, pageIndex, images);
410
478
  if (shape !== void 0) shapes.push({
411
479
  ...shape,
412
480
  paintOrder: paintOrder++
@@ -422,6 +490,44 @@ function reconstructDrawPage(page, images) {
422
490
  vectors
423
491
  };
424
492
  }
493
+ function stampVectorFrame(vector, item, pageIndex) {
494
+ if (item.kind === "rect" || item.kind === "ellipse") {
495
+ stampFrame(vector, pageIndex, {
496
+ xPt: item.xPt,
497
+ yPt: item.yPt,
498
+ widthPt: item.widthPt,
499
+ heightPt: item.heightPt
500
+ });
501
+ return;
502
+ }
503
+ if (item.kind === "line") {
504
+ stampFrame(vector, pageIndex, {
505
+ xPt: Math.min(item.x1Pt, item.x2Pt),
506
+ yPt: Math.min(item.y1Pt, item.y2Pt),
507
+ widthPt: Math.abs(item.x2Pt - item.x1Pt),
508
+ heightPt: Math.abs(item.y2Pt - item.y1Pt)
509
+ });
510
+ return;
511
+ }
512
+ if (item.kind !== "path") return;
513
+ const points = collectPathPoints(item.subpaths);
514
+ let minX = Number.POSITIVE_INFINITY;
515
+ let maxX = Number.NEGATIVE_INFINITY;
516
+ let minY = Number.POSITIVE_INFINITY;
517
+ let maxY = Number.NEGATIVE_INFINITY;
518
+ for (const point of points) {
519
+ minX = Math.min(minX, point.xPt);
520
+ maxX = Math.max(maxX, point.xPt);
521
+ minY = Math.min(minY, point.yPt);
522
+ maxY = Math.max(maxY, point.yPt);
523
+ }
524
+ stampFrame(vector, pageIndex, {
525
+ xPt: minX,
526
+ yPt: minY,
527
+ widthPt: maxX - minX,
528
+ heightPt: maxY - minY
529
+ });
530
+ }
425
531
  function layoutItemToVector(item, pageHeightPt) {
426
532
  if (item.kind === "rect") return layoutRectToVector(item, pageHeightPt);
427
533
  if (item.kind === "ellipse") return layoutEllipseToVector(item, pageHeightPt);
@@ -573,50 +679,65 @@ function layoutPathToVector(item, pageHeightPt) {
573
679
  sourcePath: item.sourcePath
574
680
  };
575
681
  }
576
- function layoutTextToShape(item, pageHeightPt) {
682
+ function layoutTextToShape(item, pageHeightPt, pageIndex) {
683
+ const frame = computeBlockFrame({ lines: [{
684
+ items: [item],
685
+ baselineY: item.yPt
686
+ }] }, pageHeightPt);
687
+ const run = textItemToContentRun(item);
688
+ stampFrame(run, pageIndex, textBoxOfItem(item, pageIndex));
689
+ const paragraph = {
690
+ kind: "paragraph",
691
+ runs: [run]
692
+ };
693
+ stampFrame(paragraph, pageIndex, textBoxOfItem(item, pageIndex));
577
694
  return {
578
- frame: computeBlockFrame({ lines: [{
579
- items: [item],
580
- baselineY: item.yPt
581
- }] }, pageHeightPt),
695
+ frame,
582
696
  rotationDeg: item.rotationDeg !== void 0 ? -item.rotationDeg : void 0,
583
697
  insetLeftPt: 0,
584
698
  insetTopPt: 0,
585
699
  insetRightPt: 0,
586
700
  insetBottomPt: 0,
587
- blocks: [{
588
- kind: "paragraph",
589
- runs: [textItemToContentRun(item)]
590
- }]
701
+ blocks: [paragraph]
591
702
  };
592
703
  }
593
704
  function vectorTopYDownPt(vector) {
594
705
  return vector.kind === "line" ? Math.min(vector.from.yPt, vector.to.yPt) : vector.frame.yPt;
595
706
  }
596
- function recoverPageVectors(page, excluded) {
707
+ function recoverPageVectors(page, pageIndex, excluded) {
597
708
  const vectors = [];
598
709
  for (const item of page.items) {
599
710
  if (excluded.has(item)) continue;
600
711
  const vector = layoutItemToVector(item, page.heightPt);
601
- if (vector !== void 0) vectors.push({
602
- ...vector,
603
- paintOrder: vectors.length
604
- });
712
+ if (vector !== void 0) {
713
+ stampVectorFrame(vector, item, pageIndex);
714
+ vectors.push({
715
+ ...vector,
716
+ paintOrder: vectors.length
717
+ });
718
+ }
605
719
  }
606
720
  if (vectors.length === 0) return;
607
721
  const topYDownPt = Math.min(...vectors.map(vectorTopYDownPt));
722
+ const block = buildDrawingBlock({
723
+ widthPt: page.widthPt,
724
+ heightPt: page.heightPt
725
+ }, vectors);
726
+ stampFrame(block, pageIndex, {
727
+ xPt: 0,
728
+ yPt: 0,
729
+ widthPt: page.widthPt,
730
+ heightPt: page.heightPt
731
+ });
608
732
  return {
609
- block: buildDrawingBlock({
610
- widthPt: page.widthPt,
611
- heightPt: page.heightPt
612
- }, vectors),
733
+ block,
613
734
  topYPt: page.heightPt - topYDownPt
614
735
  };
615
736
  }
616
- function cellBlocksFromItems(items) {
617
- return clusterIntoLines(items).map(lineToParagraph);
737
+ function cellBlocksFromItems(items, pageIndex) {
738
+ return clusterIntoLines(items).map((line) => lineToParagraph(line, pageIndex));
618
739
  }
619
- function recoverTable(page) {
740
+ function recoverTable(page, pageIndex) {
620
741
  const lattice = detectGridLattice(page.items);
621
742
  if (lattice === void 0) return;
622
743
  const rowCount = lattice.rowBoundariesDescPt.length - 1;
@@ -637,7 +758,20 @@ function recoverTable(page) {
637
758
  const rows = [];
638
759
  for (let i = 0; i < rowCount; i++) {
639
760
  const cells = [];
640
- for (let j = 0; j < columnCount; j++) cells.push({ blocks: cellBlocksFromItems(groups.get(groupKey(i, j)) ?? []) });
761
+ for (let j = 0; j < columnCount; j++) {
762
+ const cell = { blocks: cellBlocksFromItems(groups.get(groupKey(i, j)) ?? [], pageIndex) };
763
+ const cellLeftXPt = lattice.columnBoundariesAscPt[j];
764
+ const cellRightXPt = lattice.columnBoundariesAscPt[j + 1];
765
+ const cellTopYPt = lattice.rowBoundariesDescPt[i];
766
+ const cellBottomYPt = lattice.rowBoundariesDescPt[i + 1];
767
+ stampFrame(cell, pageIndex, {
768
+ xPt: cellLeftXPt,
769
+ yPt: cellBottomYPt,
770
+ widthPt: cellRightXPt - cellLeftXPt,
771
+ heightPt: cellTopYPt - cellBottomYPt
772
+ });
773
+ cells.push(cell);
774
+ }
641
775
  rows.push({
642
776
  cells,
643
777
  heightPt: lattice.rowBoundariesDescPt[i] - lattice.rowBoundariesDescPt[i + 1]
@@ -647,18 +781,21 @@ function recoverTable(page) {
647
781
  const rightXPt = lattice.columnBoundariesAscPt[columnCount];
648
782
  const topYPt = lattice.rowBoundariesDescPt[0];
649
783
  const bottomYPt = lattice.rowBoundariesDescPt[rowCount];
650
- const frame = flipY({
784
+ const pdfBox = {
651
785
  xPt: leftXPt,
652
786
  yPt: bottomYPt,
653
787
  widthPt: rightXPt - leftXPt,
654
788
  heightPt: topYPt - bottomYPt
655
- }, page.heightPt);
789
+ };
790
+ const frame = flipY(pdfBox, page.heightPt);
791
+ const table = {
792
+ kind: "table",
793
+ rows,
794
+ columnWidthsPt
795
+ };
796
+ stampFrame(table, pageIndex, pdfBox);
656
797
  return {
657
- table: {
658
- kind: "table",
659
- rows,
660
- columnWidthsPt
661
- },
798
+ table,
662
799
  frame,
663
800
  topYPt,
664
801
  consumedText,
@@ -687,7 +824,7 @@ function addToGroup(groups, row, column, item) {
687
824
  if (existing === void 0) groups.set(key, [item]);
688
825
  else existing.push(item);
689
826
  }
690
- function buildCellsFromGroups(groups, context) {
827
+ function buildCellsFromGroups(groups, pageIndex, context) {
691
828
  const cells = [];
692
829
  for (const [key, items] of groups) {
693
830
  const displayText = joinCellText(items);
@@ -695,12 +832,30 @@ function buildCellsFromGroups(groups, context) {
695
832
  const [rowPart, columnPart] = key.split(",");
696
833
  const row = Number(rowPart);
697
834
  const column = Number(columnPart);
698
- cells.push({
835
+ const cell = {
699
836
  row,
700
837
  column,
701
838
  value: inferredCellValue(displayText, row, column, context),
702
839
  displayText
840
+ };
841
+ let minX = Number.POSITIVE_INFINITY;
842
+ let maxX = Number.NEGATIVE_INFINITY;
843
+ let minY = Number.POSITIVE_INFINITY;
844
+ let maxY = Number.NEGATIVE_INFINITY;
845
+ for (const item of items) {
846
+ const { ascentPt, descentPt } = textItemVerticalExtent(item);
847
+ minX = Math.min(minX, item.xPt);
848
+ maxX = Math.max(maxX, item.xPt + (item.widthPt ?? 0));
849
+ minY = Math.min(minY, item.yPt - descentPt);
850
+ maxY = Math.max(maxY, item.yPt + ascentPt);
851
+ }
852
+ stampFrame(cell, pageIndex, {
853
+ xPt: minX,
854
+ yPt: minY,
855
+ widthPt: maxX - minX,
856
+ heightPt: maxY - minY
703
857
  });
858
+ cells.push(cell);
704
859
  }
705
860
  cells.sort((a, b) => a.row - b.row || a.column - b.column);
706
861
  return cells;
@@ -724,7 +879,7 @@ function inferredCellValue(displayText, row, column, context) {
724
879
  value: displayText
725
880
  };
726
881
  }
727
- function buildGridFromLattice(textItems, lattice, context) {
882
+ function buildGridFromLattice(textItems, lattice, pageIndex, context) {
728
883
  const groups = /* @__PURE__ */ new Map();
729
884
  for (const item of textItems) {
730
885
  const row = findRowIndex(lattice.rowBoundariesDescPt, item.yPt);
@@ -743,7 +898,7 @@ function buildGridFromLattice(textItems, lattice, context) {
743
898
  heightPt: lattice.rowBoundariesDescPt[i] - lattice.rowBoundariesDescPt[i + 1]
744
899
  });
745
900
  return {
746
- cells: buildCellsFromGroups(groups, context),
901
+ cells: buildCellsFromGroups(groups, pageIndex, context),
747
902
  columns,
748
903
  rows,
749
904
  gridlines: true
@@ -782,7 +937,7 @@ function lastColumnWidthPt(groups, columnIndex, anchorXPt) {
782
937
  }
783
938
  return maxWidthPt > 0 ? maxWidthPt : DEFAULT_COLUMN_WIDTH_FALLBACK_PT;
784
939
  }
785
- function buildGridFromTextClustering(textItems, context) {
940
+ function buildGridFromTextClustering(textItems, pageIndex, context) {
786
941
  const lines = clusterIntoLines(textItems);
787
942
  if (lines.length === 0) return {
788
943
  cells: [],
@@ -818,7 +973,7 @@ function buildGridFromTextClustering(textItems, context) {
818
973
  };
819
974
  });
820
975
  return {
821
- cells: buildCellsFromGroups(groups, context),
976
+ cells: buildCellsFromGroups(groups, pageIndex, context),
822
977
  columns,
823
978
  rows,
824
979
  gridlines: false
@@ -831,7 +986,7 @@ function reconstructSheet(page, pageIndex, sink) {
831
986
  sheetIndex: pageIndex,
832
987
  sink
833
988
  };
834
- const grid = lattice !== void 0 ? buildGridFromLattice(textItems, lattice, context) : buildGridFromTextClustering(textItems, context);
989
+ const grid = lattice !== void 0 ? buildGridFromLattice(textItems, lattice, pageIndex, context) : buildGridFromTextClustering(textItems, pageIndex, context);
835
990
  const printSettings = {
836
991
  pageSize: {
837
992
  widthPt: page.widthPt,