js.documents 1.61.0 → 1.63.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 (236) hide show
  1. package/README.md +120 -47
  2. package/dist/{blr-types-CYYC3yYU.d.cts → blr-types-DVgO1DQ9.d.cts} +1 -1
  3. package/dist/{blr-types-CYYC3yYU.d.ts → blr-types-DVgO1DQ9.d.ts} +1 -1
  4. package/dist/convert/capability.cjs +1 -0
  5. package/dist/convert/capability.d.cts +1 -1
  6. package/dist/convert/capability.d.ts +1 -1
  7. package/dist/convert/capability.js +1 -0
  8. package/dist/convert/convert.cjs +92 -38
  9. package/dist/convert/convert.d.cts +11 -4
  10. package/dist/convert/convert.d.ts +11 -4
  11. package/dist/convert/convert.js +93 -39
  12. package/dist/convert/local.cjs +15 -2
  13. package/dist/convert/local.js +15 -2
  14. package/dist/convert/port.d.cts +8 -4
  15. package/dist/convert/port.d.ts +8 -4
  16. package/dist/edit/docx/content.cjs +75 -13
  17. package/dist/edit/docx/content.d.cts +8 -2
  18. package/dist/edit/docx/content.d.ts +8 -2
  19. package/dist/edit/docx/content.js +75 -13
  20. package/dist/edit/docx/paragraph.cjs +14 -0
  21. package/dist/edit/docx/paragraph.d.cts +5 -0
  22. package/dist/edit/docx/paragraph.d.ts +5 -0
  23. package/dist/edit/docx/paragraph.js +14 -0
  24. package/dist/edit/docx/run.cjs +1 -1
  25. package/dist/edit/docx/run.js +1 -1
  26. package/dist/edit/docx/table.cjs +41 -0
  27. package/dist/edit/docx/table.d.cts +7 -1
  28. package/dist/edit/docx/table.d.ts +7 -1
  29. package/dist/edit/docx/table.js +42 -1
  30. package/dist/edit/geometry.cjs +38 -0
  31. package/dist/edit/geometry.d.cts +7 -0
  32. package/dist/edit/geometry.d.ts +7 -0
  33. package/dist/edit/geometry.js +36 -0
  34. package/dist/edit/odg/content.cjs +15 -12
  35. package/dist/edit/odg/content.js +15 -12
  36. package/dist/edit/odg/editor.d.cts +1 -1
  37. package/dist/edit/odg/editor.d.ts +1 -1
  38. package/dist/edit/odg/page.d.cts +3 -3
  39. package/dist/edit/odg/page.d.ts +3 -3
  40. package/dist/edit/odg/vector.cjs +22 -13
  41. package/dist/edit/odg/vector.d.cts +1 -1
  42. package/dist/edit/odg/vector.d.ts +1 -1
  43. package/dist/edit/odg/vector.js +23 -14
  44. package/dist/edit/odp/content.cjs +15 -0
  45. package/dist/edit/odp/content.js +16 -1
  46. package/dist/edit/odp/editor.d.cts +1 -1
  47. package/dist/edit/odp/editor.d.ts +1 -1
  48. package/dist/edit/odp/image.d.cts +1 -1
  49. package/dist/edit/odp/image.d.ts +1 -1
  50. package/dist/edit/odp/shape.cjs +11 -30
  51. package/dist/edit/odp/shape.d.cts +2 -2
  52. package/dist/edit/odp/shape.d.ts +2 -2
  53. package/dist/edit/odp/shape.js +13 -33
  54. package/dist/edit/odp/slide.cjs +11 -0
  55. package/dist/edit/odp/slide.d.cts +14 -4
  56. package/dist/edit/odp/slide.d.ts +14 -4
  57. package/dist/edit/odp/slide.js +12 -1
  58. package/dist/edit/odt/content.cjs +56 -16
  59. package/dist/edit/odt/content.d.cts +4 -2
  60. package/dist/edit/odt/content.d.ts +4 -2
  61. package/dist/edit/odt/content.js +56 -17
  62. package/dist/edit/odt/editor.d.cts +1 -1
  63. package/dist/edit/odt/editor.d.ts +1 -1
  64. package/dist/edit/odt/table.cjs +36 -0
  65. package/dist/edit/odt/table.d.cts +1 -36
  66. package/dist/edit/odt/table.d.ts +1 -36
  67. package/dist/edit/odt/table.js +37 -1
  68. package/dist/edit/pptx/content.cjs +71 -3
  69. package/dist/edit/pptx/content.js +71 -3
  70. package/dist/edit/pptx/editor.d.cts +1 -1
  71. package/dist/edit/pptx/editor.d.ts +1 -1
  72. package/dist/edit/pptx/image.d.cts +1 -1
  73. package/dist/edit/pptx/image.d.ts +1 -1
  74. package/dist/edit/pptx/shape.cjs +23 -1
  75. package/dist/edit/pptx/shape.d.cts +2 -2
  76. package/dist/edit/pptx/shape.d.ts +2 -2
  77. package/dist/edit/pptx/shape.js +23 -3
  78. package/dist/edit/pptx/slide.cjs +10 -1
  79. package/dist/edit/pptx/slide.d.cts +11 -4
  80. package/dist/edit/pptx/slide.d.ts +11 -4
  81. package/dist/edit/pptx/slide.js +10 -1
  82. package/dist/edit/pptx/table.cjs +136 -0
  83. package/dist/edit/pptx/table.d.cts +2 -0
  84. package/dist/edit/pptx/table.d.ts +2 -0
  85. package/dist/edit/pptx/table.js +131 -0
  86. package/dist/firebird/backup.d.cts +1 -1
  87. package/dist/firebird/backup.d.ts +1 -1
  88. package/dist/firebird/blr-types.cjs +2 -2
  89. package/dist/firebird/blr-types.d.cts +1 -1
  90. package/dist/firebird/blr-types.d.ts +1 -1
  91. package/dist/firebird/blr-types.js +2 -2
  92. package/dist/firebird/data.cjs +68 -14
  93. package/dist/firebird/data.d.cts +1 -1
  94. package/dist/firebird/data.d.ts +1 -1
  95. package/dist/firebird/data.js +68 -14
  96. package/dist/firebird/schema.cjs +13 -1
  97. package/dist/firebird/schema.d.cts +1 -1
  98. package/dist/firebird/schema.d.ts +1 -1
  99. package/dist/firebird/schema.js +13 -1
  100. package/dist/fonts/obfuscation.cjs +50 -0
  101. package/dist/fonts/obfuscation.d.cts +9 -0
  102. package/dist/fonts/obfuscation.d.ts +9 -0
  103. package/dist/fonts/obfuscation.js +46 -0
  104. package/dist/fonts/odf.cjs +86 -0
  105. package/dist/fonts/odf.d.cts +9 -0
  106. package/dist/fonts/odf.d.ts +9 -0
  107. package/dist/fonts/odf.js +84 -0
  108. package/dist/fonts/ooxml.cjs +129 -0
  109. package/dist/fonts/ooxml.d.cts +9 -0
  110. package/dist/fonts/ooxml.d.ts +9 -0
  111. package/dist/fonts/ooxml.js +127 -0
  112. package/dist/fonts/registry.cjs +18 -0
  113. package/dist/fonts/registry.d.cts +2 -0
  114. package/dist/fonts/registry.d.ts +2 -0
  115. package/dist/fonts/registry.js +16 -0
  116. package/dist/{geometry-DvwdrIij.d.cts → geometry-DaJr8yQW.d.cts} +2 -2
  117. package/dist/{geometry-DvwdrIij.d.ts → geometry-DaJr8yQW.d.ts} +2 -2
  118. package/dist/hsqldb/binary-script.cjs +154 -0
  119. package/dist/hsqldb/binary-script.d.cts +15 -0
  120. package/dist/hsqldb/binary-script.d.ts +15 -0
  121. package/dist/hsqldb/binary-script.js +151 -0
  122. package/dist/hsqldb/cache.cjs +18 -11
  123. package/dist/hsqldb/cache.d.cts +9 -4
  124. package/dist/hsqldb/cache.d.ts +9 -4
  125. package/dist/hsqldb/cache.js +18 -11
  126. package/dist/hsqldb/rowformat.cjs +60 -16
  127. package/dist/hsqldb/rowformat.d.cts +2 -21
  128. package/dist/hsqldb/rowformat.d.ts +2 -21
  129. package/dist/hsqldb/rowformat.js +60 -17
  130. package/dist/{image-BZDy72Jb.d.cts → image-7snmKIxn.d.cts} +1 -1
  131. package/dist/{image-B-xQWYYS.d.ts → image-Cs8xF753.d.ts} +1 -1
  132. package/dist/{image-CeqwL-Qs.d.ts → image-DHcA9kaK.d.ts} +1 -1
  133. package/dist/{image-DWX6cNOD.d.cts → image-M5SezZVI.d.cts} +1 -1
  134. package/dist/index.cjs +86 -3
  135. package/dist/index.d.cts +33 -21
  136. package/dist/index.d.ts +33 -21
  137. package/dist/index.js +18 -5
  138. package/dist/layout/cell-typing.cjs +209 -0
  139. package/dist/layout/cell-typing.d.cts +22 -0
  140. package/dist/layout/cell-typing.d.ts +22 -0
  141. package/dist/layout/cell-typing.js +208 -0
  142. package/dist/layout/drawing.cjs +193 -17
  143. package/dist/layout/drawing.js +193 -17
  144. package/dist/layout/engine.cjs +46 -29
  145. package/dist/layout/engine.d.cts +0 -2
  146. package/dist/layout/engine.d.ts +0 -2
  147. package/dist/layout/engine.js +47 -30
  148. package/dist/layout/lattice.cjs +139 -0
  149. package/dist/layout/lattice.d.cts +20 -0
  150. package/dist/layout/lattice.d.ts +20 -0
  151. package/dist/layout/lattice.js +135 -0
  152. package/dist/layout/reconstruct.cjs +176 -113
  153. package/dist/layout/reconstruct.d.cts +2 -0
  154. package/dist/layout/reconstruct.d.ts +2 -0
  155. package/dist/layout/reconstruct.js +173 -110
  156. package/dist/layout/shared.cjs +52 -0
  157. package/dist/layout/shared.d.cts +4 -2
  158. package/dist/layout/shared.d.ts +4 -2
  159. package/dist/layout/shared.js +51 -1
  160. package/dist/layout/sheets.cjs +45 -11
  161. package/dist/layout/sheets.js +46 -12
  162. package/dist/layout/slides.cjs +7 -7
  163. package/dist/layout/slides.d.cts +0 -3
  164. package/dist/layout/slides.d.ts +0 -3
  165. package/dist/layout/slides.js +7 -7
  166. package/dist/markdown/write.cjs +19 -6
  167. package/dist/markdown/write.js +19 -6
  168. package/dist/mathml/layout.cjs +2 -2
  169. package/dist/mathml/layout.d.cts +1 -1
  170. package/dist/mathml/layout.d.ts +1 -1
  171. package/dist/mathml/layout.js +2 -2
  172. package/dist/model/embedded-drawing.cjs +32 -0
  173. package/dist/model/embedded-drawing.d.cts +8 -0
  174. package/dist/model/embedded-drawing.d.ts +8 -0
  175. package/dist/model/embedded-drawing.js +30 -0
  176. package/dist/model/formula.cjs +31 -0
  177. package/dist/model/formula.d.cts +6 -6
  178. package/dist/model/formula.d.ts +6 -6
  179. package/dist/model/formula.js +27 -0
  180. package/dist/model/geometry.d.cts +1 -1
  181. package/dist/model/geometry.d.ts +1 -1
  182. package/dist/model/paint-order.cjs +15 -0
  183. package/dist/model/paint-order.d.cts +14 -0
  184. package/dist/model/paint-order.d.ts +14 -0
  185. package/dist/model/paint-order.js +14 -0
  186. package/dist/odb/components.cjs +12 -0
  187. package/dist/odb/components.d.cts +6 -0
  188. package/dist/odb/components.d.ts +6 -0
  189. package/dist/odb/components.js +10 -0
  190. package/dist/odb/read.cjs +11 -7
  191. package/dist/odb/read.d.cts +3 -2
  192. package/dist/odb/read.d.ts +3 -2
  193. package/dist/odb/read.js +11 -7
  194. package/dist/odf/formula/detect.cjs +86 -18
  195. package/dist/odf/formula/detect.d.cts +10 -6
  196. package/dist/odf/formula/detect.d.ts +10 -6
  197. package/dist/odf/formula/detect.js +86 -19
  198. package/dist/odf/formula/read.cjs +4 -16
  199. package/dist/odf/formula/read.d.cts +4 -8
  200. package/dist/odf/formula/read.d.ts +4 -8
  201. package/dist/odf/formula/read.js +5 -17
  202. package/dist/odf/odp/read.cjs +9 -19
  203. package/dist/odf/odp/read.d.cts +2 -7
  204. package/dist/odf/odp/read.d.ts +2 -7
  205. package/dist/odf/odp/read.js +10 -20
  206. package/dist/odf/odt/read.cjs +63 -23
  207. package/dist/odf/odt/read.d.cts +2 -7
  208. package/dist/odf/odt/read.d.ts +2 -7
  209. package/dist/odf/odt/read.js +64 -24
  210. package/dist/omml/write.cjs +258 -0
  211. package/dist/omml/write.d.cts +2 -0
  212. package/dist/omml/write.d.ts +2 -0
  213. package/dist/omml/write.js +256 -0
  214. package/dist/registry-CrSqLIcn.d.ts +19 -0
  215. package/dist/registry-CtPhMD0f.d.cts +19 -0
  216. package/dist/rowformat-Cl2exlEh.d.cts +25 -0
  217. package/dist/rowformat-Cl2exlEh.d.ts +25 -0
  218. package/dist/{schema-Acco3Ezi.d.cts → schema-BeR_KJ0X.d.cts} +3 -1
  219. package/dist/{schema-VkAA6pF5.d.ts → schema-CSKwSb_v.d.ts} +3 -1
  220. package/dist/{shape-BUfjw5eZ.d.cts → shape-BhkP6HB8.d.cts} +6 -2
  221. package/dist/{shape-CTkl6kt8.d.ts → shape-BkVcwPcf.d.ts} +6 -2
  222. package/dist/{shape-BfN3m52m.d.ts → shape-CVXedeL7.d.ts} +3 -2
  223. package/dist/{shape-CN2ycxOo.d.cts → shape-CXZ6fejV.d.cts} +3 -2
  224. package/dist/table-C3CPZ--2.d.cts +35 -0
  225. package/dist/table-DjYcNOFm.d.cts +44 -0
  226. package/dist/table-DqfqMkVq.d.ts +44 -0
  227. package/dist/table-DvS_7UQS.d.ts +35 -0
  228. package/dist/{vector-ClohqsOe.d.cts → vector-Puuqu_IT.d.cts} +4 -0
  229. package/dist/{vector-ClohqsOe.d.ts → vector-Puuqu_IT.d.ts} +4 -0
  230. package/dist/write-DuyfnbL_.d.cts +16 -0
  231. package/dist/write-Zqwx6pka.d.ts +16 -0
  232. package/package.json +4 -4
  233. package/dist/odf/formula/placeholder.cjs +0 -36
  234. package/dist/odf/formula/placeholder.d.cts +0 -14
  235. package/dist/odf/formula/placeholder.d.ts +0 -14
  236. package/dist/odf/formula/placeholder.js +0 -36
@@ -1,5 +1,8 @@
1
1
  import { flipY } from "../model/geometry.js";
2
+ import { buildDrawingBlock } from "../model/embedded-drawing.js";
2
3
  import { throwIfAborted } from "../ports/abort.js";
4
+ import { inferCellValue } from "./cell-typing.js";
5
+ import { detectGridLattice, findColumnIndex, findRowIndex } from "./lattice.js";
3
6
  import { CONTENT_FORMAT_VERSION } from "document-schema.js";
4
7
  import { STANDARD_METRICS, resolveStandardFont } from "pdf-codec";
5
8
  //#region src/layout/reconstruct.ts
@@ -134,7 +137,9 @@ function buildSection(pages, images) {
134
137
  };
135
138
  }
136
139
  function reconstructPageBlocks(page, images) {
137
- const textItems = page.items.filter((i) => i.kind === "text");
140
+ const recoveredTable = recoverTable(page);
141
+ const consumedText = recoveredTable?.consumedText;
142
+ const textItems = page.items.filter((i) => i.kind === "text" && consumedText?.has(i) !== true);
138
143
  const imageItems = page.items.filter((i) => i.kind === "image");
139
144
  const paragraphs = clusterIntoParagraphs(clusterIntoLines(textItems));
140
145
  const positioned = [];
@@ -155,6 +160,15 @@ function reconstructPageBlocks(page, images) {
155
160
  }
156
161
  });
157
162
  }
163
+ if (recoveredTable !== void 0) positioned.push({
164
+ yPt: recoveredTable.topYPt,
165
+ block: recoveredTable.table
166
+ });
167
+ const recoveredVectors = recoverPageVectors(page, recoveredTable?.latticeItems ?? NO_ITEMS);
168
+ if (recoveredVectors !== void 0) positioned.push({
169
+ yPt: recoveredVectors.topYPt,
170
+ block: recoveredVectors.block
171
+ });
158
172
  positioned.sort((a, b) => b.yPt - a.yPt);
159
173
  return positioned.map((p) => p.block);
160
174
  }
@@ -212,7 +226,9 @@ function reconstructPresentation(doc, options) {
212
226
  };
213
227
  }
214
228
  function reconstructSlide(page, images) {
215
- const textItems = page.items.filter((i) => i.kind === "text");
229
+ const recoveredTable = recoverTable(page);
230
+ const consumedText = recoveredTable?.consumedText;
231
+ const textItems = page.items.filter((i) => i.kind === "text" && consumedText?.has(i) !== true);
216
232
  const imageItems = page.items.filter((i) => i.kind === "image");
217
233
  const textShapes = clusterIntoBlocks(clusterIntoLines(textItems)).map((block) => blockToShape(block, page.heightPt));
218
234
  const imageShapes = [];
@@ -220,15 +236,38 @@ function reconstructSlide(page, images) {
220
236
  const shape = imageToShape(img, page.heightPt, images);
221
237
  if (shape !== void 0) imageShapes.push(shape);
222
238
  }
239
+ const recoveredVectors = recoverPageVectors(page, recoveredTable?.latticeItems ?? NO_ITEMS);
240
+ const vectorShapes = recoveredVectors === void 0 ? [] : [wrapBlockInShape(recoveredVectors.block, {
241
+ xPt: 0,
242
+ yPt: 0,
243
+ widthPt: page.widthPt,
244
+ heightPt: page.heightPt
245
+ })];
246
+ const tableShapes = recoveredTable === void 0 ? [] : [wrapBlockInShape(recoveredTable.table, recoveredTable.frame)];
223
247
  return {
224
248
  size: {
225
249
  widthPt: page.widthPt,
226
250
  heightPt: page.heightPt
227
251
  },
228
- shapes: [...imageShapes, ...textShapes],
252
+ shapes: [
253
+ ...vectorShapes,
254
+ ...imageShapes,
255
+ ...tableShapes,
256
+ ...textShapes
257
+ ],
229
258
  notes: page.notes ?? ""
230
259
  };
231
260
  }
261
+ function wrapBlockInShape(block, frame) {
262
+ return {
263
+ frame,
264
+ insetLeftPt: 0,
265
+ insetTopPt: 0,
266
+ insetRightPt: 0,
267
+ insetBottomPt: 0,
268
+ blocks: [block]
269
+ };
270
+ }
232
271
  function splitLineByLargeGaps(line) {
233
272
  const segments = [];
234
273
  let current = [];
@@ -352,14 +391,27 @@ function reconstructDrawing(doc, options) {
352
391
  function reconstructDrawPage(page, images) {
353
392
  const vectors = [];
354
393
  const shapes = [];
355
- for (const item of page.items) if (item.kind === "rect") vectors.push(layoutRectToVector(item, page.heightPt));
356
- else if (item.kind === "ellipse") vectors.push(layoutEllipseToVector(item, page.heightPt));
357
- else if (item.kind === "line") vectors.push(layoutLineToVector(item, page.heightPt));
358
- else if (item.kind === "path") vectors.push(layoutPathToVector(item, page.heightPt));
359
- else if (item.kind === "text") shapes.push(layoutTextToShape(item, page.heightPt));
360
- else if (item.kind === "image") {
361
- const shape = imageToShape(item, page.heightPt, images);
362
- if (shape !== void 0) shapes.push(shape);
394
+ let paintOrder = 0;
395
+ for (const item of page.items) {
396
+ const vector = layoutItemToVector(item, page.heightPt);
397
+ if (vector !== void 0) {
398
+ vectors.push({
399
+ ...vector,
400
+ paintOrder: paintOrder++
401
+ });
402
+ continue;
403
+ }
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);
410
+ if (shape !== void 0) shapes.push({
411
+ ...shape,
412
+ paintOrder: paintOrder++
413
+ });
414
+ }
363
415
  }
364
416
  return {
365
417
  size: {
@@ -370,6 +422,12 @@ function reconstructDrawPage(page, images) {
370
422
  vectors
371
423
  };
372
424
  }
425
+ function layoutItemToVector(item, pageHeightPt) {
426
+ if (item.kind === "rect") return layoutRectToVector(item, pageHeightPt);
427
+ if (item.kind === "ellipse") return layoutEllipseToVector(item, pageHeightPt);
428
+ if (item.kind === "line") return layoutLineToVector(item, pageHeightPt);
429
+ if (item.kind === "path") return layoutPathToVector(item, pageHeightPt);
430
+ }
373
431
  function layoutRectToVector(item, pageHeightPt) {
374
432
  return {
375
433
  kind: "rect",
@@ -532,99 +590,82 @@ function layoutTextToShape(item, pageHeightPt) {
532
590
  }]
533
591
  };
534
592
  }
535
- function extractLineCandidates(items) {
536
- const segments = [];
537
- for (const item of items) {
538
- if (item.kind === "line") {
539
- segments.push({
540
- x1Pt: item.x1Pt,
541
- y1Pt: item.y1Pt,
542
- x2Pt: item.x2Pt,
543
- y2Pt: item.y2Pt
544
- });
545
- continue;
546
- }
547
- if (item.kind === "path" && item.stroke !== void 0 && item.subpaths.length === 1) {
548
- const subpath = item.subpaths[0];
549
- if (subpath.segments.length === 1 && subpath.segments[0].kind === "line") {
550
- const segment = subpath.segments[0];
551
- segments.push({
552
- x1Pt: subpath.startXPt,
553
- y1Pt: subpath.startYPt,
554
- x2Pt: segment.xPt,
555
- y2Pt: segment.yPt
556
- });
557
- }
558
- }
559
- }
560
- return segments;
593
+ function vectorTopYDownPt(vector) {
594
+ return vector.kind === "line" ? Math.min(vector.from.yPt, vector.to.yPt) : vector.frame.yPt;
561
595
  }
562
- const AXIS_ALIGNMENT_TOLERANCE_PT = .5;
563
- const MIN_GRIDLINE_LENGTH_PT = 4;
564
- function classifyAxisLine(seg) {
565
- const dx = Math.abs(seg.x2Pt - seg.x1Pt);
566
- const dy = Math.abs(seg.y2Pt - seg.y1Pt);
567
- if (dy <= AXIS_ALIGNMENT_TOLERANCE_PT && dx >= MIN_GRIDLINE_LENGTH_PT) return {
568
- axis: "horizontal",
569
- position: (seg.y1Pt + seg.y2Pt) / 2,
570
- spanPt: dx
571
- };
572
- if (dx <= AXIS_ALIGNMENT_TOLERANCE_PT && dy >= MIN_GRIDLINE_LENGTH_PT) return {
573
- axis: "vertical",
574
- position: (seg.x1Pt + seg.x2Pt) / 2,
575
- spanPt: dy
576
- };
577
- }
578
- const POSITION_DEDUPE_TOLERANCE_PT = .5;
579
- function dedupeAxisLines(lines, descending) {
580
- const sorted = [...lines].sort((a, b) => descending ? b.position - a.position : a.position - b.position);
581
- const result = [];
582
- for (const candidate of sorted) {
583
- const last = result[result.length - 1];
584
- if (last !== void 0 && Math.abs(candidate.position - last.position) <= POSITION_DEDUPE_TOLERANCE_PT) last.spanPt = Math.max(last.spanPt, candidate.spanPt);
585
- else result.push({
586
- position: candidate.position,
587
- spanPt: candidate.spanPt
596
+ function recoverPageVectors(page, excluded) {
597
+ const vectors = [];
598
+ for (const item of page.items) {
599
+ if (excluded.has(item)) continue;
600
+ const vector = layoutItemToVector(item, page.heightPt);
601
+ if (vector !== void 0) vectors.push({
602
+ ...vector,
603
+ paintOrder: vectors.length
588
604
  });
589
605
  }
590
- return result;
591
- }
592
- const MIN_GRIDLINE_COUNT_PER_AXIS = 3;
593
- const GRID_SPAN_CONSISTENCY_RATIO = .9;
594
- function isRegularLattice(lines) {
595
- if (lines.length < MIN_GRIDLINE_COUNT_PER_AXIS) return false;
596
- const maxSpanPt = Math.max(...lines.map((l) => l.spanPt));
597
- return lines.filter((l) => l.spanPt >= maxSpanPt * GRID_SPAN_CONSISTENCY_RATIO).length >= MIN_GRIDLINE_COUNT_PER_AXIS;
598
- }
599
- function detectGridLattice(items) {
600
- const horizontal = [];
601
- const vertical = [];
602
- for (const seg of extractLineCandidates(items)) {
603
- const classified = classifyAxisLine(seg);
604
- if (classified === void 0) continue;
605
- (classified.axis === "horizontal" ? horizontal : vertical).push(classified);
606
- }
607
- const rowBoundaries = dedupeAxisLines(horizontal, true);
608
- const columnBoundaries = dedupeAxisLines(vertical, false);
609
- if (!isRegularLattice(rowBoundaries) || !isRegularLattice(columnBoundaries)) return;
606
+ if (vectors.length === 0) return;
607
+ const topYDownPt = Math.min(...vectors.map(vectorTopYDownPt));
610
608
  return {
611
- rowBoundariesDescPt: rowBoundaries.map((l) => l.position),
612
- columnBoundariesAscPt: columnBoundaries.map((l) => l.position)
609
+ block: buildDrawingBlock({
610
+ widthPt: page.widthPt,
611
+ heightPt: page.heightPt
612
+ }, vectors),
613
+ topYPt: page.heightPt - topYDownPt
613
614
  };
614
615
  }
615
- const OUTER_EDGE_TOLERANCE_PT = 3;
616
- function findRowIndex(rowBoundariesDescPt, yPt) {
617
- const lastIndex = rowBoundariesDescPt.length - 1;
618
- if (yPt > rowBoundariesDescPt[0] + OUTER_EDGE_TOLERANCE_PT || yPt < rowBoundariesDescPt[lastIndex] - OUTER_EDGE_TOLERANCE_PT) return;
619
- for (let i = 0; i < lastIndex; i++) if (yPt > rowBoundariesDescPt[i + 1]) return i;
620
- return lastIndex - 1;
616
+ function cellBlocksFromItems(items) {
617
+ return clusterIntoLines(items).map(lineToParagraph);
621
618
  }
622
- function findColumnIndex(columnBoundariesAscPt, xPt) {
623
- const lastIndex = columnBoundariesAscPt.length - 1;
624
- if (xPt < columnBoundariesAscPt[0] - OUTER_EDGE_TOLERANCE_PT || xPt > columnBoundariesAscPt[lastIndex] + OUTER_EDGE_TOLERANCE_PT) return;
625
- for (let j = 0; j < lastIndex; j++) if (xPt < columnBoundariesAscPt[j + 1]) return j;
626
- return lastIndex - 1;
619
+ function recoverTable(page) {
620
+ const lattice = detectGridLattice(page.items);
621
+ if (lattice === void 0) return;
622
+ const rowCount = lattice.rowBoundariesDescPt.length - 1;
623
+ const columnCount = lattice.columnBoundariesAscPt.length - 1;
624
+ const groups = /* @__PURE__ */ new Map();
625
+ const consumedText = /* @__PURE__ */ new Set();
626
+ for (const item of page.items) {
627
+ if (item.kind !== "text") continue;
628
+ const row = findRowIndex(lattice.rowBoundariesDescPt, item.yPt);
629
+ const column = findColumnIndex(lattice.columnBoundariesAscPt, item.xPt);
630
+ if (row === void 0 || column === void 0) continue;
631
+ addToGroup(groups, row, column, item);
632
+ consumedText.add(item);
633
+ }
634
+ if (consumedText.size === 0) return;
635
+ const columnWidthsPt = [];
636
+ for (let j = 0; j < columnCount; j++) columnWidthsPt.push(lattice.columnBoundariesAscPt[j + 1] - lattice.columnBoundariesAscPt[j]);
637
+ const rows = [];
638
+ for (let i = 0; i < rowCount; i++) {
639
+ const cells = [];
640
+ for (let j = 0; j < columnCount; j++) cells.push({ blocks: cellBlocksFromItems(groups.get(groupKey(i, j)) ?? []) });
641
+ rows.push({
642
+ cells,
643
+ heightPt: lattice.rowBoundariesDescPt[i] - lattice.rowBoundariesDescPt[i + 1]
644
+ });
645
+ }
646
+ const leftXPt = lattice.columnBoundariesAscPt[0];
647
+ const rightXPt = lattice.columnBoundariesAscPt[columnCount];
648
+ const topYPt = lattice.rowBoundariesDescPt[0];
649
+ const bottomYPt = lattice.rowBoundariesDescPt[rowCount];
650
+ const frame = flipY({
651
+ xPt: leftXPt,
652
+ yPt: bottomYPt,
653
+ widthPt: rightXPt - leftXPt,
654
+ heightPt: topYPt - bottomYPt
655
+ }, page.heightPt);
656
+ return {
657
+ table: {
658
+ kind: "table",
659
+ rows,
660
+ columnWidthsPt
661
+ },
662
+ frame,
663
+ topYPt,
664
+ consumedText,
665
+ latticeItems: lattice.sourceItems
666
+ };
627
667
  }
668
+ const NO_ITEMS = /* @__PURE__ */ new Set();
628
669
  function joinCellText(items) {
629
670
  const sorted = [...items].sort((a, b) => a.xPt - b.xPt);
630
671
  let text = "";
@@ -646,26 +687,44 @@ function addToGroup(groups, row, column, item) {
646
687
  if (existing === void 0) groups.set(key, [item]);
647
688
  else existing.push(item);
648
689
  }
649
- function buildCellsFromGroups(groups) {
690
+ function buildCellsFromGroups(groups, context) {
650
691
  const cells = [];
651
692
  for (const [key, items] of groups) {
652
693
  const displayText = joinCellText(items);
653
694
  if (displayText.length === 0) continue;
654
695
  const [rowPart, columnPart] = key.split(",");
696
+ const row = Number(rowPart);
697
+ const column = Number(columnPart);
655
698
  cells.push({
656
- row: Number(rowPart),
657
- column: Number(columnPart),
658
- value: {
659
- kind: "string",
660
- value: displayText
661
- },
699
+ row,
700
+ column,
701
+ value: inferredCellValue(displayText, row, column, context),
662
702
  displayText
663
703
  });
664
704
  }
665
705
  cells.sort((a, b) => a.row - b.row || a.column - b.column);
666
706
  return cells;
667
707
  }
668
- function buildGridFromLattice(textItems, lattice) {
708
+ function inferredCellValue(displayText, row, column, context) {
709
+ const inference = inferCellValue(displayText);
710
+ if (inference === void 0) return {
711
+ kind: "string",
712
+ value: displayText
713
+ };
714
+ const reported = {
715
+ sheetIndex: context.sheetIndex,
716
+ row,
717
+ column,
718
+ displayText,
719
+ ...inference
720
+ };
721
+ context.sink?.(reported);
722
+ return inference.outcome === "retyped" ? inference.value : {
723
+ kind: "string",
724
+ value: displayText
725
+ };
726
+ }
727
+ function buildGridFromLattice(textItems, lattice, context) {
669
728
  const groups = /* @__PURE__ */ new Map();
670
729
  for (const item of textItems) {
671
730
  const row = findRowIndex(lattice.rowBoundariesDescPt, item.yPt);
@@ -684,7 +743,7 @@ function buildGridFromLattice(textItems, lattice) {
684
743
  heightPt: lattice.rowBoundariesDescPt[i] - lattice.rowBoundariesDescPt[i + 1]
685
744
  });
686
745
  return {
687
- cells: buildCellsFromGroups(groups),
746
+ cells: buildCellsFromGroups(groups, context),
688
747
  columns,
689
748
  rows,
690
749
  gridlines: true
@@ -723,7 +782,7 @@ function lastColumnWidthPt(groups, columnIndex, anchorXPt) {
723
782
  }
724
783
  return maxWidthPt > 0 ? maxWidthPt : DEFAULT_COLUMN_WIDTH_FALLBACK_PT;
725
784
  }
726
- function buildGridFromTextClustering(textItems) {
785
+ function buildGridFromTextClustering(textItems, context) {
727
786
  const lines = clusterIntoLines(textItems);
728
787
  if (lines.length === 0) return {
729
788
  cells: [],
@@ -759,16 +818,20 @@ function buildGridFromTextClustering(textItems) {
759
818
  };
760
819
  });
761
820
  return {
762
- cells: buildCellsFromGroups(groups),
821
+ cells: buildCellsFromGroups(groups, context),
763
822
  columns,
764
823
  rows,
765
824
  gridlines: false
766
825
  };
767
826
  }
768
- function reconstructSheet(page, pageIndex) {
827
+ function reconstructSheet(page, pageIndex, sink) {
769
828
  const textItems = page.items.filter((i) => i.kind === "text");
770
829
  const lattice = detectGridLattice(page.items);
771
- const grid = lattice !== void 0 ? buildGridFromLattice(textItems, lattice) : buildGridFromTextClustering(textItems);
830
+ const context = {
831
+ sheetIndex: pageIndex,
832
+ sink
833
+ };
834
+ const grid = lattice !== void 0 ? buildGridFromLattice(textItems, lattice, context) : buildGridFromTextClustering(textItems, context);
772
835
  const printSettings = {
773
836
  pageSize: {
774
837
  widthPt: page.widthPt,
@@ -792,7 +855,7 @@ function reconstructSpreadsheet(doc, options) {
792
855
  const signal = options?.signal;
793
856
  const sheets = doc.pages.map((page, index) => {
794
857
  throwIfAborted(signal);
795
- return reconstructSheet(page, index);
858
+ return reconstructSheet(page, index, options?.onCellTypeInference);
796
859
  });
797
860
  return {
798
861
  kind: "spreadsheet",
@@ -43,6 +43,56 @@ function alignmentOffsetPt(alignment, contentWidthPt, lineWidthPt) {
43
43
  if (alignment === "right") return Math.max(0, contentWidthPt - lineWidthPt);
44
44
  return 0;
45
45
  }
46
+ const GAP_DETECTION_EPSILON_PT = .01;
47
+ function justifyLineGapsPt(line, targetWidthPt, measurer) {
48
+ const fragments = line.fragments;
49
+ const extrasPt = new Array(fragments.length).fill(0);
50
+ if (fragments.length < 2) return extrasPt;
51
+ const gapIndices = [];
52
+ for (let i = 0; i < fragments.length - 1; i++) {
53
+ const fragment = fragments[i];
54
+ const next = fragments[i + 1];
55
+ const naturalEndPt = fragment.xOffsetPt + measurer.widthOfTextAtSize(fragment.text, fragment.font, fragment.sizePt);
56
+ if (next.xOffsetPt - naturalEndPt > GAP_DETECTION_EPSILON_PT) gapIndices.push(i);
57
+ }
58
+ if (gapIndices.length === 0) return extrasPt;
59
+ const slackPt = targetWidthPt - line.widthPt;
60
+ if (slackPt <= 0) return extrasPt;
61
+ const extraPerGapPt = slackPt / gapIndices.length;
62
+ let cumulativePt = 0;
63
+ let gapPointer = 0;
64
+ for (let i = 0; i < fragments.length; i++) {
65
+ extrasPt[i] = cumulativePt;
66
+ if (gapPointer < gapIndices.length && gapIndices[gapPointer] === i) {
67
+ cumulativePt += extraPerGapPt;
68
+ gapPointer++;
69
+ }
70
+ }
71
+ return extrasPt;
72
+ }
73
+ function pushBorderLine(border, x1Pt, y1Pt, x2Pt, y2Pt, sourcePath, out) {
74
+ if (border === void 0) return;
75
+ out.push({
76
+ kind: "line",
77
+ x1Pt,
78
+ y1Pt,
79
+ x2Pt,
80
+ y2Pt,
81
+ color: border.color,
82
+ widthPt: border.widthPt,
83
+ sourcePath
84
+ });
85
+ }
86
+ function pushCellBorderLines(borders, frameYDown, pageHeightPt, sourcePath, out) {
87
+ const leftXPt = frameYDown.xPt;
88
+ const rightXPt = frameYDown.xPt + frameYDown.widthPt;
89
+ const topYPt = pageHeightPt - frameYDown.yPt;
90
+ const bottomYPt = pageHeightPt - (frameYDown.yPt + frameYDown.heightPt);
91
+ pushBorderLine(borders.top, leftXPt, topYPt, rightXPt, topYPt, sourcePath, out);
92
+ pushBorderLine(borders.bottom, leftXPt, bottomYPt, rightXPt, bottomYPt, sourcePath, out);
93
+ pushBorderLine(borders.left, leftXPt, topYPt, leftXPt, bottomYPt, sourcePath, out);
94
+ pushBorderLine(borders.right, rightXPt, topYPt, rightXPt, bottomYPt, sourcePath, out);
95
+ }
46
96
  function decodeImageDimensions(format, bytes) {
47
97
  if (format === "jpeg") {
48
98
  const info = (0, pdf_codec.readJpegInfo)(bytes);
@@ -97,7 +147,9 @@ exports.NOMINAL_TEXT_SIZE_PT = NOMINAL_TEXT_SIZE_PT;
97
147
  exports.alignmentOffsetPt = alignmentOffsetPt;
98
148
  exports.effectiveStyledRuns = effectiveStyledRuns;
99
149
  exports.estimateRowHeightPt = estimateRowHeightPt;
150
+ exports.justifyLineGapsPt = justifyLineGapsPt;
100
151
  exports.lineNaturalHeightPt = lineNaturalHeightPt;
152
+ exports.pushCellBorderLines = pushCellBorderLines;
101
153
  exports.registerImage = registerImage;
102
154
  exports.runFont = runFont;
103
155
  exports.sumColumnWidthsPt = sumColumnWidthsPt;
@@ -1,5 +1,5 @@
1
1
  import { i as LayoutFont, t as Alignment } from "../style-DkamR3aY.cjs";
2
- import { ContentImageBlock, ContentRun, ContentTableRow, LayoutImageAsset } from "document-schema.js";
2
+ import { Box, ContentCellBorders, ContentImageBlock, ContentRun, ContentTableRow, LayoutImageAsset, LayoutItem } from "document-schema.js";
3
3
  import { StyledRun, TextMeasurer, WrappedLine } from "pdf-codec";
4
4
  //#region src/layout/shared.d.ts
5
5
  declare const NOMINAL_TEXT_SIZE_PT = 18;
@@ -8,8 +8,10 @@ declare function toStyledRuns(runs: readonly ContentRun[], fontScale?: number):
8
8
  declare function effectiveStyledRuns(runs: readonly ContentRun[], fontScale?: number): StyledRun[];
9
9
  declare function lineNaturalHeightPt(line: WrappedLine, measurer: TextMeasurer, fallback: StyledRun): number;
10
10
  declare function alignmentOffsetPt(alignment: Alignment | undefined, contentWidthPt: number, lineWidthPt: number): number;
11
+ declare function justifyLineGapsPt(line: WrappedLine, targetWidthPt: number, measurer: TextMeasurer): readonly number[];
12
+ declare function pushCellBorderLines(borders: ContentCellBorders, frameYDown: Box, pageHeightPt: number, sourcePath: string | undefined, out: LayoutItem[]): void;
11
13
  declare function registerImage(block: ContentImageBlock, images: Record<string, LayoutImageAsset>): string;
12
14
  declare function sumColumnWidthsPt(columnWidthsPt: readonly number[], startIndex: number, span: number): number;
13
15
  declare function estimateRowHeightPt(row: ContentTableRow, measurer: TextMeasurer, columnWidthsPt: readonly number[], scale: number): number;
14
16
  //#endregion
15
- export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, lineNaturalHeightPt, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
17
+ export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
@@ -1,5 +1,5 @@
1
1
  import { i as LayoutFont, t as Alignment } from "../style-DkamR3aY.js";
2
- import { ContentImageBlock, ContentRun, ContentTableRow, LayoutImageAsset } from "document-schema.js";
2
+ import { Box, ContentCellBorders, ContentImageBlock, ContentRun, ContentTableRow, LayoutImageAsset, LayoutItem } from "document-schema.js";
3
3
  import { StyledRun, TextMeasurer, WrappedLine } from "pdf-codec";
4
4
  //#region src/layout/shared.d.ts
5
5
  declare const NOMINAL_TEXT_SIZE_PT = 18;
@@ -8,8 +8,10 @@ declare function toStyledRuns(runs: readonly ContentRun[], fontScale?: number):
8
8
  declare function effectiveStyledRuns(runs: readonly ContentRun[], fontScale?: number): StyledRun[];
9
9
  declare function lineNaturalHeightPt(line: WrappedLine, measurer: TextMeasurer, fallback: StyledRun): number;
10
10
  declare function alignmentOffsetPt(alignment: Alignment | undefined, contentWidthPt: number, lineWidthPt: number): number;
11
+ declare function justifyLineGapsPt(line: WrappedLine, targetWidthPt: number, measurer: TextMeasurer): readonly number[];
12
+ declare function pushCellBorderLines(borders: ContentCellBorders, frameYDown: Box, pageHeightPt: number, sourcePath: string | undefined, out: LayoutItem[]): void;
11
13
  declare function registerImage(block: ContentImageBlock, images: Record<string, LayoutImageAsset>): string;
12
14
  declare function sumColumnWidthsPt(columnWidthsPt: readonly number[], startIndex: number, span: number): number;
13
15
  declare function estimateRowHeightPt(row: ContentTableRow, measurer: TextMeasurer, columnWidthsPt: readonly number[], scale: number): number;
14
16
  //#endregion
15
- export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, lineNaturalHeightPt, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
17
+ export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
@@ -43,6 +43,56 @@ function alignmentOffsetPt(alignment, contentWidthPt, lineWidthPt) {
43
43
  if (alignment === "right") return Math.max(0, contentWidthPt - lineWidthPt);
44
44
  return 0;
45
45
  }
46
+ const GAP_DETECTION_EPSILON_PT = .01;
47
+ function justifyLineGapsPt(line, targetWidthPt, measurer) {
48
+ const fragments = line.fragments;
49
+ const extrasPt = new Array(fragments.length).fill(0);
50
+ if (fragments.length < 2) return extrasPt;
51
+ const gapIndices = [];
52
+ for (let i = 0; i < fragments.length - 1; i++) {
53
+ const fragment = fragments[i];
54
+ const next = fragments[i + 1];
55
+ const naturalEndPt = fragment.xOffsetPt + measurer.widthOfTextAtSize(fragment.text, fragment.font, fragment.sizePt);
56
+ if (next.xOffsetPt - naturalEndPt > GAP_DETECTION_EPSILON_PT) gapIndices.push(i);
57
+ }
58
+ if (gapIndices.length === 0) return extrasPt;
59
+ const slackPt = targetWidthPt - line.widthPt;
60
+ if (slackPt <= 0) return extrasPt;
61
+ const extraPerGapPt = slackPt / gapIndices.length;
62
+ let cumulativePt = 0;
63
+ let gapPointer = 0;
64
+ for (let i = 0; i < fragments.length; i++) {
65
+ extrasPt[i] = cumulativePt;
66
+ if (gapPointer < gapIndices.length && gapIndices[gapPointer] === i) {
67
+ cumulativePt += extraPerGapPt;
68
+ gapPointer++;
69
+ }
70
+ }
71
+ return extrasPt;
72
+ }
73
+ function pushBorderLine(border, x1Pt, y1Pt, x2Pt, y2Pt, sourcePath, out) {
74
+ if (border === void 0) return;
75
+ out.push({
76
+ kind: "line",
77
+ x1Pt,
78
+ y1Pt,
79
+ x2Pt,
80
+ y2Pt,
81
+ color: border.color,
82
+ widthPt: border.widthPt,
83
+ sourcePath
84
+ });
85
+ }
86
+ function pushCellBorderLines(borders, frameYDown, pageHeightPt, sourcePath, out) {
87
+ const leftXPt = frameYDown.xPt;
88
+ const rightXPt = frameYDown.xPt + frameYDown.widthPt;
89
+ const topYPt = pageHeightPt - frameYDown.yPt;
90
+ const bottomYPt = pageHeightPt - (frameYDown.yPt + frameYDown.heightPt);
91
+ pushBorderLine(borders.top, leftXPt, topYPt, rightXPt, topYPt, sourcePath, out);
92
+ pushBorderLine(borders.bottom, leftXPt, bottomYPt, rightXPt, bottomYPt, sourcePath, out);
93
+ pushBorderLine(borders.left, leftXPt, topYPt, leftXPt, bottomYPt, sourcePath, out);
94
+ pushBorderLine(borders.right, rightXPt, topYPt, rightXPt, bottomYPt, sourcePath, out);
95
+ }
46
96
  function decodeImageDimensions(format, bytes) {
47
97
  if (format === "jpeg") {
48
98
  const info = readJpegInfo(bytes);
@@ -93,4 +143,4 @@ function estimateRowHeightPt(row, measurer, columnWidthsPt, scale) {
93
143
  return max;
94
144
  }
95
145
  //#endregion
96
- export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, lineNaturalHeightPt, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
146
+ export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_model_geometry = require("../model/geometry.cjs");
2
3
  const require_layout_shared = require("./shared.cjs");
3
4
  const require_ports_abort = require("../ports/abort.cjs");
4
5
  let document_schema_js = require("document-schema.js");
@@ -182,15 +183,39 @@ function axisSpanSizePt(axis, startIndex, span) {
182
183
  if (startPosition === void 0) return 0;
183
184
  return require_layout_shared.sumColumnWidthsPt(axis.sizesPt, startPosition, span);
184
185
  }
185
- function renderCellText(cell, rowCells, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageHeightPt, measurer, out) {
186
+ function resolveCellFrame(cell, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt) {
186
187
  const columnPosition = columnAxis.positionByIndex.get(cell.column);
187
188
  const rowPosition = rowAxis.positionByIndex.get(cell.row);
188
189
  if (columnPosition === void 0 || rowPosition === void 0) return;
189
- const ownWidthPt = axisSpanSizePt(columnAxis, cell.column, cell.colSpan ?? 1);
190
- const heightPt = axisSpanSizePt(rowAxis, cell.row, cell.rowSpan ?? 1);
191
- const xLeftPt = gridLeftXPt + columnAxis.offsetsPt[columnPosition];
192
- const yTopDownPt = gridTopYDownPt + rowAxis.offsetsPt[rowPosition];
193
- const alignment = defaultAlignmentForValue(cell.value.kind);
190
+ return {
191
+ xPt: gridLeftXPt + columnAxis.offsetsPt[columnPosition],
192
+ yPt: gridTopYDownPt + rowAxis.offsetsPt[rowPosition],
193
+ widthPt: axisSpanSizePt(columnAxis, cell.column, cell.colSpan ?? 1),
194
+ heightPt: axisSpanSizePt(rowAxis, cell.row, cell.rowSpan ?? 1)
195
+ };
196
+ }
197
+ function renderCellBackground(cell, frameYDown, pageHeightPt, out) {
198
+ if (cell.background === void 0) return;
199
+ const flipped = require_model_geometry.flipY(frameYDown, pageHeightPt);
200
+ out.push({
201
+ kind: "rect",
202
+ xPt: flipped.xPt,
203
+ yPt: flipped.yPt,
204
+ widthPt: flipped.widthPt,
205
+ heightPt: flipped.heightPt,
206
+ fill: cell.background,
207
+ sourcePath: cell.sourcePath
208
+ });
209
+ }
210
+ const DEFAULT_CELL_VERTICAL_ALIGNMENT = "bottom";
211
+ function verticalLineTopYDownPt(verticalAlignment, cellTopYDownPt, cellHeightPt, lineHeightPt) {
212
+ if (verticalAlignment === "top") return cellTopYDownPt + CELL_TEXT_PADDING_PT;
213
+ if (verticalAlignment === "middle") return cellTopYDownPt + Math.max(CELL_TEXT_PADDING_PT, (cellHeightPt - lineHeightPt) / 2);
214
+ return cellTopYDownPt + Math.max(CELL_TEXT_PADDING_PT, cellHeightPt - CELL_TEXT_PADDING_PT - lineHeightPt);
215
+ }
216
+ function renderCellText(cell, frameYDown, rowCells, columnAxis, pageHeightPt, measurer, out) {
217
+ const { xPt: xLeftPt, yPt: yTopDownPt, widthPt: ownWidthPt, heightPt } = frameYDown;
218
+ const alignment = cell.alignment ?? defaultAlignmentForValue(cell.value.kind);
194
219
  const numericLike = isNumericLikeValue(cell.value.kind);
195
220
  const styledRuns = cellStyledRuns(cell);
196
221
  const naturalLine = (0, pdf_codec.wrapRunsToWidth)(styledRuns, measurer, Number.POSITIVE_INFINITY)[0];
@@ -220,7 +245,7 @@ function renderCellText(cell, rowCells, columnAxis, rowAxis, gridLeftXPt, gridTo
220
245
  const alignOffsetPt = require_layout_shared.alignmentOffsetPt(alignment, availableWidthPt, lineWidthPt);
221
246
  const textStartXPt = xLeftPt + CELL_TEXT_PADDING_PT + alignOffsetPt;
222
247
  const lineHeightPt = require_layout_shared.lineNaturalHeightPt(naturalLine, measurer, styledRuns[0]);
223
- const baselineYDownPt = yTopDownPt + Math.max(CELL_TEXT_PADDING_PT, heightPt - CELL_TEXT_PADDING_PT - lineHeightPt) + naturalLine.ascentPt;
248
+ const baselineYDownPt = verticalLineTopYDownPt(cell.verticalAlignment ?? DEFAULT_CELL_VERTICAL_ALIGNMENT, yTopDownPt, heightPt, lineHeightPt) + naturalLine.ascentPt;
224
249
  for (const fragment of fragments) {
225
250
  const textItem = {
226
251
  kind: "text",
@@ -380,18 +405,27 @@ function convertSheetToPages(sheet, measurer, signal, out) {
380
405
  const gridTopYDownPt = margins.topPt + gutter.heightPt;
381
406
  const gridWidthPt = columnAxis.offsetsPt[columnAxis.offsetsPt.length - 1];
382
407
  const gridHeightPt = rowAxis.offsetsPt[rowAxis.offsetsPt.length - 1];
383
- const items = [];
384
- if (printSettings.gridlines) renderGridlines(gridLeftXPt, gridTopYDownPt, gridWidthPt, gridHeightPt, columnAxis.offsetsPt, rowAxis.offsetsPt, pageSize.heightPt, items);
385
- if (printSettings.headers) renderHeaderLabels(gutter, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageSize.heightPt, measurer, items);
408
+ const backgroundItems = [];
409
+ const borderItems = [];
410
+ const textItems = [];
386
411
  for (const rowIndex of rowAxis.indices) {
387
412
  const rowCells = cellsByRow.get(rowIndex);
388
413
  if (rowCells === void 0) continue;
389
414
  for (const [columnIndex, cell] of rowCells) {
390
415
  require_ports_abort.throwIfAborted(signal);
391
416
  if (!columnAxis.positionByIndex.has(columnIndex) || hiddenColumnIndices.has(columnIndex) || hiddenRowIndices.has(cell.row)) continue;
392
- renderCellText(cell, rowCells, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageSize.heightPt, measurer, items);
417
+ const cellFrame = resolveCellFrame(cell, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt);
418
+ if (cellFrame === void 0) continue;
419
+ renderCellBackground(cell, cellFrame, pageSize.heightPt, backgroundItems);
420
+ if (cell.borders !== void 0) require_layout_shared.pushCellBorderLines(cell.borders, cellFrame, pageSize.heightPt, cell.sourcePath, borderItems);
421
+ renderCellText(cell, cellFrame, rowCells, columnAxis, pageSize.heightPt, measurer, textItems);
393
422
  }
394
423
  }
424
+ const items = [...backgroundItems];
425
+ if (printSettings.gridlines) renderGridlines(gridLeftXPt, gridTopYDownPt, gridWidthPt, gridHeightPt, columnAxis.offsetsPt, rowAxis.offsetsPt, pageSize.heightPt, items);
426
+ items.push(...borderItems);
427
+ if (printSettings.headers) renderHeaderLabels(gutter, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageSize.heightPt, measurer, items);
428
+ items.push(...textItems);
395
429
  out.push({
396
430
  widthPt: pageSize.widthPt,
397
431
  heightPt: pageSize.heightPt,