@pixerate/editor 0.24.0 → 0.25.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 (133) hide show
  1. package/README.md +71 -1
  2. package/THIRD_PARTY_NOTICES.md +29 -0
  3. package/dist/agent/index.cjs +10 -9
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +1 -1
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +4 -3
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/canvas/index.cjs +3173 -340
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.d.cts +617 -4
  12. package/dist/canvas/index.d.ts +617 -4
  13. package/dist/canvas/index.js +3105 -272
  14. package/dist/canvas/index.js.map +1 -1
  15. package/dist/chunk-4BVP64JJ.cjs +1406 -0
  16. package/dist/chunk-4BVP64JJ.cjs.map +1 -0
  17. package/dist/{chunk-XNORY7M6.cjs → chunk-7WISYZFO.cjs} +105 -50
  18. package/dist/chunk-7WISYZFO.cjs.map +1 -0
  19. package/dist/{chunk-OLZJXL4R.cjs → chunk-AL6JMGWW.cjs} +59 -25
  20. package/dist/chunk-AL6JMGWW.cjs.map +1 -0
  21. package/dist/chunk-BVP3TSLH.cjs +69 -0
  22. package/dist/chunk-BVP3TSLH.cjs.map +1 -0
  23. package/dist/{chunk-MCSJFWAO.cjs → chunk-C7P22VIP.cjs} +670 -96
  24. package/dist/chunk-C7P22VIP.cjs.map +1 -0
  25. package/dist/{chunk-PGNZKFQS.js → chunk-ECCCYKGL.js} +76 -21
  26. package/dist/chunk-ECCCYKGL.js.map +1 -0
  27. package/dist/{chunk-3CN2WD3X.js → chunk-FH6F67DN.js} +646 -72
  28. package/dist/chunk-FH6F67DN.js.map +1 -0
  29. package/dist/chunk-HRMEDT2L.js +1406 -0
  30. package/dist/chunk-HRMEDT2L.js.map +1 -0
  31. package/dist/{chunk-ITBSKI26.js → chunk-IXHSYOVY.js} +941 -9
  32. package/dist/chunk-IXHSYOVY.js.map +1 -0
  33. package/dist/{chunk-FODNLX5N.js → chunk-NAXVVS5I.js} +38 -4
  34. package/dist/chunk-NAXVVS5I.js.map +1 -0
  35. package/dist/chunk-O5RYH2PG.js +69 -0
  36. package/dist/chunk-O5RYH2PG.js.map +1 -0
  37. package/dist/{chunk-SBCZ6RN5.cjs → chunk-PO6A6QQH.cjs} +1039 -107
  38. package/dist/chunk-PO6A6QQH.cjs.map +1 -0
  39. package/dist/{chunk-3LV6RRPH.js → chunk-QGYDWPRM.js} +2 -2
  40. package/dist/{chunk-U5KWZU4X.js → chunk-RR7F5GUM.js} +2632 -129
  41. package/dist/chunk-RR7F5GUM.js.map +1 -0
  42. package/dist/{chunk-5S3Z4PPF.js → chunk-UAKDG62Z.js} +232 -25
  43. package/dist/chunk-UAKDG62Z.js.map +1 -0
  44. package/dist/{chunk-SML64VJG.cjs → chunk-V3CHHWOE.cjs} +4 -4
  45. package/dist/{chunk-SML64VJG.cjs.map → chunk-V3CHHWOE.cjs.map} +1 -1
  46. package/dist/chunk-WSQKHXW7.cjs +5726 -0
  47. package/dist/chunk-WSQKHXW7.cjs.map +1 -0
  48. package/dist/{chunk-D27YFC46.cjs → chunk-X4N4WUKB.cjs} +267 -60
  49. package/dist/chunk-X4N4WUKB.cjs.map +1 -0
  50. package/dist/commands/index.cjs +74 -1
  51. package/dist/commands/index.cjs.map +1 -1
  52. package/dist/commands/index.d.cts +34 -1
  53. package/dist/commands/index.d.ts +34 -1
  54. package/dist/commands/index.js +73 -0
  55. package/dist/commands/index.js.map +1 -1
  56. package/dist/compare/index.cjs +3 -3
  57. package/dist/compare/index.d.cts +1 -1
  58. package/dist/compare/index.d.ts +1 -1
  59. package/dist/compare/index.js +2 -2
  60. package/dist/controller-BIJiNoVs.d.cts +1842 -0
  61. package/dist/controller-BIJiNoVs.d.ts +1842 -0
  62. package/dist/{documents-BQjzJNe2.d.ts → documents-CHT1U5Vs.d.ts} +10 -0
  63. package/dist/{documents-KRTPhvst.d.cts → documents-Gp7wb0Me.d.cts} +10 -0
  64. package/dist/extensions/index.cjs +53 -6
  65. package/dist/extensions/index.cjs.map +1 -1
  66. package/dist/extensions/index.d.cts +12 -4
  67. package/dist/extensions/index.d.ts +12 -4
  68. package/dist/extensions/index.js +53 -6
  69. package/dist/generation/index.cjs +1013 -69
  70. package/dist/generation/index.cjs.map +1 -1
  71. package/dist/generation/index.d.cts +474 -13
  72. package/dist/generation/index.d.ts +474 -13
  73. package/dist/generation/index.js +976 -32
  74. package/dist/generation/index.js.map +1 -1
  75. package/dist/image-editor/index.cjs +3385 -1275
  76. package/dist/image-editor/index.cjs.map +1 -1
  77. package/dist/image-editor/index.d.cts +693 -128
  78. package/dist/image-editor/index.d.ts +693 -128
  79. package/dist/image-editor/index.js +3325 -1215
  80. package/dist/image-editor/index.js.map +1 -1
  81. package/dist/{index-fJrlkJCd.d.ts → index-7a6bHTLy.d.ts} +494 -5
  82. package/dist/{index-BhJBSm2d.d.cts → index-Csd5qI8u.d.cts} +494 -5
  83. package/dist/index.cjs +1491 -45
  84. package/dist/index.cjs.map +1 -1
  85. package/dist/index.d.cts +110 -19
  86. package/dist/index.d.ts +110 -19
  87. package/dist/index.js +1464 -18
  88. package/dist/index.js.map +1 -1
  89. package/dist/mention-text-CDnCFd3c.d.cts +53 -0
  90. package/dist/mention-text-CDnCFd3c.d.ts +53 -0
  91. package/dist/model-C1zApQM8.d.cts +219 -0
  92. package/dist/model-C1zApQM8.d.ts +219 -0
  93. package/dist/persistence/index.d.cts +3 -120
  94. package/dist/persistence/index.d.ts +3 -120
  95. package/dist/{registry-GJI4gToU.d.cts → registry-CEgwXED1.d.cts} +12 -1
  96. package/dist/{registry-GJI4gToU.d.ts → registry-CEgwXED1.d.ts} +12 -1
  97. package/dist/serializers/index.cjs +12 -4
  98. package/dist/serializers/index.cjs.map +1 -1
  99. package/dist/serializers/index.d.cts +39 -12
  100. package/dist/serializers/index.d.ts +39 -12
  101. package/dist/serializers/index.js +12 -4
  102. package/dist/spreadsheet/index.cjs +127 -3
  103. package/dist/spreadsheet/index.cjs.map +1 -1
  104. package/dist/spreadsheet/index.d.cts +431 -11
  105. package/dist/spreadsheet/index.d.ts +431 -11
  106. package/dist/spreadsheet/index.js +127 -3
  107. package/dist/storage-BpFfspHm.d.cts +120 -0
  108. package/dist/storage-BpFfspHm.d.ts +120 -0
  109. package/dist/tokens/index.cjs +115 -0
  110. package/dist/tokens/index.cjs.map +1 -0
  111. package/dist/tokens/index.d.cts +212 -0
  112. package/dist/tokens/index.d.ts +212 -0
  113. package/dist/tokens/index.js +115 -0
  114. package/dist/tokens/index.js.map +1 -0
  115. package/dist/{track-changes-BK5sVf4_.d.cts → track-changes-D_VAPELi.d.cts} +95 -11
  116. package/dist/{track-changes-CDjCrwKe.d.ts → track-changes-Db_fGEvx.d.ts} +95 -11
  117. package/package.json +6 -1
  118. package/dist/chunk-3CN2WD3X.js.map +0 -1
  119. package/dist/chunk-5S3Z4PPF.js.map +0 -1
  120. package/dist/chunk-D27YFC46.cjs.map +0 -1
  121. package/dist/chunk-FODNLX5N.js.map +0 -1
  122. package/dist/chunk-ITBSKI26.js.map +0 -1
  123. package/dist/chunk-MA2F5KHF.cjs +0 -3223
  124. package/dist/chunk-MA2F5KHF.cjs.map +0 -1
  125. package/dist/chunk-MCSJFWAO.cjs.map +0 -1
  126. package/dist/chunk-OLZJXL4R.cjs.map +0 -1
  127. package/dist/chunk-PGNZKFQS.js.map +0 -1
  128. package/dist/chunk-SBCZ6RN5.cjs.map +0 -1
  129. package/dist/chunk-U5KWZU4X.js.map +0 -1
  130. package/dist/chunk-XNORY7M6.cjs.map +0 -1
  131. package/dist/controller-BhLLAoi8.d.cts +0 -1000
  132. package/dist/controller-BhLLAoi8.d.ts +0 -1000
  133. /package/dist/{chunk-3LV6RRPH.js.map → chunk-QGYDWPRM.js.map} +0 -0
package/dist/index.js CHANGED
@@ -40,12 +40,15 @@ import {
40
40
  Autocorrect,
41
41
  BUILT_IN_IMPORT_ADAPTERS,
42
42
  Bookmark,
43
+ CHARACTER_STYLE_MARK_NAME,
43
44
  COMMENT_MARK_NAME,
45
+ CharacterStyle,
44
46
  ColorHighlighter,
45
47
  Comments,
46
48
  CrossReference,
47
49
  DEFAULT_AUTOCORRECT_EXCEPTIONS,
48
50
  DEFAULT_DOCX_MAX_IMAGE_SIZE,
51
+ DEFAULT_STYLES,
49
52
  DEFAULT_ZIP_MAX_ENTRIES,
50
53
  DEFAULT_ZIP_MAX_TOTAL_SIZE,
51
54
  DOCX_MIME_TYPES,
@@ -68,11 +71,15 @@ import {
68
71
  MAX_FIND_PATTERN_LENGTH,
69
72
  Markdown,
70
73
  Mention,
74
+ NORMAL_STYLE_ID,
71
75
  Outline,
76
+ ParagraphStyles,
72
77
  RichClipboard,
73
78
  SMILIE_REPLACEMENTS,
79
+ STYLE_ID_ATTRIBUTE,
74
80
  SlashCommands,
75
81
  SmilieReplacer,
82
+ StyleRegistry,
76
83
  TableOfContents,
77
84
  TemplateSuggestions,
78
85
  ZipArchive,
@@ -82,6 +89,7 @@ import {
82
89
  autocorrectPluginKey,
83
90
  buildOutlineTree,
84
91
  capitalizeSentenceRules,
92
+ captureSelectionFormat,
85
93
  commentsPluginKey,
86
94
  compareInEditor,
87
95
  compileFindPattern,
@@ -92,8 +100,10 @@ import {
92
100
  createImportContext,
93
101
  createMentionExtension,
94
102
  createOutlineStore,
103
+ createParagraphStylesStore,
95
104
  createRichTextPreset,
96
105
  createSearchBudget,
106
+ createStyleRegistry,
97
107
  crossReferencePluginKey,
98
108
  defaultAutocorrectRules,
99
109
  defaultImportRegistry,
@@ -125,7 +135,10 @@ import {
125
135
  getFindReplaceStore,
126
136
  getFootnotes,
127
137
  getImportAccept,
138
+ getMentionNodes,
128
139
  getOutline,
140
+ getParagraphStyleAt,
141
+ getStyleRegistry,
129
142
  getTableOfContentsEntries,
130
143
  handleImageInsertion,
131
144
  htmlImportAdapter,
@@ -136,10 +149,13 @@ import {
136
149
  insertImageNode,
137
150
  insertImportedDocument,
138
151
  isInsidePromptToken,
152
+ isParagraphStyleAvailable,
139
153
  isUnsafeZipPath,
154
+ isValidStyleId,
140
155
  markdownImportAdapter,
141
156
  navigateToHeading,
142
157
  outlinePluginKey,
158
+ paragraphStylesPluginKey,
143
159
  parseReplacement,
144
160
  plainTextImportAdapter,
145
161
  readZip,
@@ -147,7 +163,9 @@ import {
147
163
  removeImageNode,
148
164
  richClipboardPluginKey,
149
165
  rtfImportAdapter,
166
+ safeCSSValue,
150
167
  searchDocument,
168
+ setMentionRoleAt,
151
169
  smartQuoteRules,
152
170
  smilieAutocorrectRules,
153
171
  symbolRules,
@@ -160,13 +178,13 @@ import {
160
178
  validateFindPattern,
161
179
  writeRichClipboard,
162
180
  zipCrc32
163
- } from "./chunk-ITBSKI26.js";
181
+ } from "./chunk-IXHSYOVY.js";
164
182
  import {
165
183
  compareDocuments,
166
184
  compareHtml,
167
185
  diffChanges,
168
186
  diffSequences
169
- } from "./chunk-FODNLX5N.js";
187
+ } from "./chunk-NAXVVS5I.js";
170
188
  import {
171
189
  INSTRUCTION_REGEX,
172
190
  TEMPLATE_REGEX,
@@ -201,20 +219,37 @@ import {
201
219
  rtfToPlainText,
202
220
  sanitizeImportedHtml,
203
221
  serializeRichClipboardPayload
204
- } from "./chunk-3LV6RRPH.js";
222
+ } from "./chunk-QGYDWPRM.js";
205
223
  import {
224
+ CONDITIONAL_FORMAT_ICON_SETS,
225
+ CONDITIONAL_FORMAT_PRESETS,
226
+ CONDITIONAL_FORMAT_STYLE_PRESETS,
227
+ CONDITIONAL_FORMAT_TIME_PERIODS,
228
+ ConditionalFormatEngine,
229
+ DATA_VALIDATION_ERROR_STYLE_OPTIONS,
230
+ DATA_VALIDATION_OPERATOR_OPTIONS,
231
+ DATA_VALIDATION_TYPE_OPTIONS,
206
232
  DEFAULT_COLUMN_WIDTH,
233
+ DEFAULT_CONDITIONAL_FORMAT_STYLE,
234
+ DEFAULT_DATA_VALIDATION_MESSAGE,
235
+ DEFAULT_DATA_VALIDATION_TITLE,
207
236
  DEFAULT_ROW_HEIGHT,
208
237
  DataSourceBinder,
209
238
  DependencyGraph,
239
+ EMPTY_CONDITIONAL_FORMAT_OVERLAY,
240
+ MAX_DEFINED_NAME_LENGTH,
241
+ MAX_SHEET_NAME_LENGTH,
210
242
  NUMBER_FORMAT_PRESETS,
211
243
  SPREADSHEET_CLIPBOARD_MIME,
212
244
  SPREADSHEET_IMPORT_ADAPTERS,
213
245
  SPREADSHEET_TABLE_ACTIONS,
214
246
  SpreadsheetController,
247
+ adjustRangeForStructuralChange,
248
+ adjustRangesForStructuralChange,
215
249
  aggregateValues,
216
250
  applyFormulaSuggestion,
217
251
  bindSpreadsheetTableActions,
252
+ blendConditionalFormatColors,
218
253
  buildSpreadsheetView,
219
254
  cellFormatForNumberFormat,
220
255
  clampMenuPosition,
@@ -222,44 +257,86 @@ import {
222
257
  compareCellValues,
223
258
  computeFillTarget,
224
259
  computeRowGroups,
260
+ conditionalFormatContrastColor,
261
+ conditionalFormatIconCount,
262
+ conditionalFormatNumber,
263
+ conditionalFormatStyleString,
264
+ copySheetName,
265
+ createConditionalFormatRule,
225
266
  createSpreadsheetClipboardData,
226
267
  csvImportAdapter,
268
+ defaultIconThresholds,
269
+ deleteSheetInFormula,
270
+ describeConditionalFormat,
271
+ describeDataValidation,
272
+ evaluateConditionalFormats,
227
273
  extractCellDependencies,
274
+ extractNameDependencies,
228
275
  fillSeries,
276
+ findDataValidation,
277
+ findInvalidCells,
278
+ forEachRangeCell,
229
279
  formatCellDisplay,
230
280
  formatCellForDisplay,
281
+ formatRuleRanges,
282
+ formatSheetPrefix,
231
283
  formatValueWithCode,
284
+ formulaIdentifiers,
285
+ getConditionalFormatCss,
286
+ getConditionalFormatIcon,
287
+ getDataBarCss,
232
288
  getFillDirection,
233
289
  getFormulaCaretContext,
234
290
  getFormulaHints,
291
+ getNameManagerRows,
235
292
  getRowSection,
293
+ getSheetTabMenuItems,
236
294
  getSpreadsheetMenuItems,
237
295
  getTableSections,
296
+ getValidationListValues,
238
297
  importFileIntoSpreadsheet,
239
298
  isBlankValue,
240
299
  isGeneralNumberFormat,
300
+ isLambdaDefinition,
241
301
  isSingleCellRange,
242
302
  mapFormulaReferences,
243
303
  matchesFilterRule,
304
+ matchesTimePeriod,
305
+ nextSheetName,
244
306
  normalizeRange,
245
307
  numberFormatForCellFormat,
246
308
  offsetFormulaReferences,
247
309
  parseHtmlTable,
310
+ parseRuleRanges,
311
+ quoteSheetName,
248
312
  rangeContains,
249
313
  rangeContainsRange,
314
+ rangesContain,
250
315
  rangesIntersect,
251
316
  readSpreadsheetClipboard,
252
317
  rebaseClipboardRows,
253
318
  registerSpreadsheetImportAdapters,
254
319
  remapFormulaReferences,
320
+ renameNameInFormula,
321
+ renameSheetInFormula,
255
322
  roundFloat,
256
323
  rowPassesFilters,
324
+ ruleAnchor,
325
+ ruleFormulaAt,
257
326
  runSpreadsheetMenuItem,
258
327
  serializeHtmlTable,
328
+ sheetDropIndex,
329
+ sheetNameNeedsQuotes,
259
330
  shiftFormulaReferences,
331
+ shiftRuleFormula,
332
+ subtractRange,
333
+ subtractRangeFromRanges,
260
334
  toNumber,
261
- tsvImportAdapter
262
- } from "./chunk-U5KWZU4X.js";
335
+ tsvImportAdapter,
336
+ validateCellInput,
337
+ validateDefinedName,
338
+ validateSheetName
339
+ } from "./chunk-RR7F5GUM.js";
263
340
  import {
264
341
  escapeCsvField,
265
342
  parseCsv,
@@ -278,7 +355,6 @@ import {
278
355
  } from "./chunk-2H7ZHPEJ.js";
279
356
  import {
280
357
  MARKDOWN_MENTION_SPLIT_REGEX,
281
- MENTION_REGEX,
282
358
  escapeHtml,
283
359
  extractMentions,
284
360
  extractMentionsFromDoc,
@@ -293,13 +369,22 @@ import {
293
369
  preprocessMarkdownMentions,
294
370
  sanitizeHtml,
295
371
  stripMarkdownCode
296
- } from "./chunk-PGNZKFQS.js";
372
+ } from "./chunk-ECCCYKGL.js";
373
+ import {
374
+ MENTION_REGEX,
375
+ findTextMentions,
376
+ formatMentionText,
377
+ setMentionRoleInText
378
+ } from "./chunk-O5RYH2PG.js";
297
379
  import {
298
380
  BLOCK_CHANGE_ATTRIBUTE,
299
381
  CommentStore,
300
382
  DELETION_MARK_NAME,
301
383
  FORMAT_CHANGE_MARK_NAME,
302
384
  INSERTION_MARK_NAME,
385
+ MOVE_FROM_CLASS,
386
+ MOVE_ID_ATTRIBUTE,
387
+ MOVE_TO_CLASS,
303
388
  TRACK_CHANGES_SKIP_META,
304
389
  TrackChanges,
305
390
  TrackChangesStore,
@@ -314,15 +399,19 @@ import {
314
399
  getTrackChangesStore,
315
400
  getTrackedChangeAt,
316
401
  getTrackedChanges,
402
+ isMoveSized,
317
403
  isTrackChangesEnabled,
318
404
  resolveTrackedChanges,
319
- trackChangesPluginKey
320
- } from "./chunk-5S3Z4PPF.js";
405
+ trackChangesPluginKey,
406
+ trackedChangeLabel
407
+ } from "./chunk-UAKDG62Z.js";
321
408
  import {
322
409
  FORMULA_ERRORS,
323
410
  FormulaEvaluator,
411
+ FormulaLambda,
324
412
  FormulaParser,
325
413
  MAX_FORMULA_ARRAY_SIZE,
414
+ MAX_LAMBDA_DEPTH,
326
415
  MAX_NUMBER_FORMAT_CODE_CHARS,
327
416
  NumberFormat,
328
417
  WHOLE_COLUMN_END_ROW,
@@ -344,6 +433,7 @@ import {
344
433
  getFormulaSignatureParts,
345
434
  indexToColName,
346
435
  isFormulaError,
436
+ isFormulaLambda,
347
437
  listFormulaFunctions,
348
438
  numberFormatColorToCss,
349
439
  numberToText,
@@ -360,7 +450,7 @@ import {
360
450
  tokenizeFormula,
361
451
  unregisterFormulaFunction,
362
452
  wildcardToRegExp
363
- } from "./chunk-3CN2WD3X.js";
453
+ } from "./chunk-FH6F67DN.js";
364
454
 
365
455
  // src/controller.ts
366
456
  import { Editor } from "@tiptap/core";
@@ -600,10 +690,1026 @@ var FileImportController = class {
600
690
  function createFileImportController(getTarget, options) {
601
691
  return new FileImportController(getTarget, options);
602
692
  }
693
+ function summarizeImportStructure(outcomes) {
694
+ const reports = outcomes.map((outcome) => outcome.result?.structure).filter((report) => !!report);
695
+ if (!reports.length) return null;
696
+ const modes = new Set(reports.map((report) => report.mode));
697
+ const sum = (pick) => reports.reduce((total, report) => total + pick(report), 0);
698
+ return {
699
+ files: reports.length,
700
+ mode: modes.size > 1 ? "mixed" : reports[0].mode,
701
+ headings: sum((r) => r.counts.headings),
702
+ lists: sum((r) => r.counts.lists),
703
+ tables: sum((r) => r.counts.tables),
704
+ paragraphs: sum((r) => r.counts.paragraphs),
705
+ multiColumnPages: sum((r) => r.multiColumnPages),
706
+ confidence: Math.round(sum((r) => r.confidence) / reports.length * 100) / 100
707
+ };
708
+ }
709
+
710
+ // src/import/pdf-layout.ts
711
+ var MAX_COLS = 63;
712
+ var MAX_TABLE_ROWS = 2e3;
713
+ var MAX_RULES = 2e3;
714
+ var MAX_DEPTH = 4;
715
+ var BULLET_GLYPH_RE = /^[•◦▪▫●○■□‣⁃∙·➢►▶✓✔❖]\s*/;
716
+ var BULLET_DASH_RE = /^[-–—*]\s+/;
717
+ var ORDERED_RE = /^(?:\((\d{1,3}|[a-zA-Z]|[ivxlcIVXLC]{1,6})\)|(\d{1,3}|[a-zA-Z]|[ivxlcIVXLC]{1,6})[.)])\s+/;
718
+ var MARKER_ONLY_RE = /^(?:[•◦▪▫●○■□‣⁃∙·➢►▶✓✔❖]|\(?(?:\d{1,3}|[a-zA-Z]|[ivxlcIVXLC]{1,6})[.)])$/;
719
+ var PAGE_NUMBER_RE = /^(?:page\s+)?(?:\d{1,4}|[ivxlcdm]{1,7})(?:\s*(?:of|\/)\s*\d{1,4})?$/i;
720
+ var DASHED_PAGE_NUMBER_RE = /^[-–—]\s*\d{1,4}\s*[-–—]$/;
721
+ var SENTENCE_END_RE = /[.!?:;]["'”’)\]]?$/;
722
+ var BOLD_FONT_RE = /bold|black|heavy|semibold|demi/i;
723
+ var ITALIC_FONT_RE = /italic|oblique/i;
724
+ function minOf(list, fn) {
725
+ let min = Infinity;
726
+ for (const item of list) min = Math.min(min, fn(item));
727
+ return min;
728
+ }
729
+ function maxOf(list, fn) {
730
+ let max = -Infinity;
731
+ for (const item of list) max = Math.max(max, fn(item));
732
+ return max;
733
+ }
734
+ function lowerBound(values, target) {
735
+ let lo = 0;
736
+ let hi = values.length;
737
+ while (lo < hi) {
738
+ const mid = lo + hi >> 1;
739
+ if (values[mid] < target) lo = mid + 1;
740
+ else hi = mid;
741
+ }
742
+ return lo;
743
+ }
744
+ function median(values) {
745
+ if (!values.length) return 0;
746
+ const sorted = [...values].sort((a, b) => a - b);
747
+ const mid = sorted.length >> 1;
748
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
749
+ }
750
+ var countWords = (text) => {
751
+ let words = 0;
752
+ let inWord = false;
753
+ for (let i = 0; i < text.length; i++) {
754
+ const space = text.charCodeAt(i) <= 32;
755
+ if (!space && !inWord) words++;
756
+ inWord = !space;
757
+ }
758
+ return words;
759
+ };
760
+ var collapse = (text) => text.replace(/\s+/g, " ").trim();
761
+ function runSize(run) {
762
+ if (run.fontSize && run.fontSize > 0) return run.fontSize;
763
+ if (run.height && run.height > 0) return run.height;
764
+ return 10;
765
+ }
766
+ function buildFragments(runs) {
767
+ const items = runs.filter((run) => typeof run.text === "string" && run.text.trim() !== "" && Number.isFinite(run.x) && Number.isFinite(run.y)).map((run) => {
768
+ const size = runSize(run);
769
+ const width = run.width !== void 0 && run.width >= 0 ? run.width : run.text.length * size * 0.5;
770
+ return {
771
+ text: run.text,
772
+ x0: run.x,
773
+ x1: run.x + width,
774
+ y: run.y,
775
+ size,
776
+ bold: run.bold ?? BOLD_FONT_RE.test(run.fontName ?? ""),
777
+ italic: run.italic ?? ITALIC_FONT_RE.test(run.fontName ?? "")
778
+ };
779
+ });
780
+ items.sort((a, b) => b.y - a.y || a.x0 - b.x0);
781
+ const frags = [];
782
+ let i = 0;
783
+ while (i < items.length) {
784
+ const anchor = items[i];
785
+ let j = i + 1;
786
+ while (j < items.length && anchor.y - items[j].y <= Math.max(1, Math.min(anchor.size, items[j].size) * 0.5)) j++;
787
+ const row = items.slice(i, j).sort((a, b) => a.x0 - b.x0);
788
+ i = j;
789
+ let current = null;
790
+ const finish = () => {
791
+ if (!current) return;
792
+ let best = "";
793
+ let bestChars = -1;
794
+ current.styleChars.forEach((chars, key) => {
795
+ if (chars > bestChars) {
796
+ best = key;
797
+ bestChars = chars;
798
+ }
799
+ });
800
+ const [size, bold, italic] = best.split("|");
801
+ current.size = Number(size);
802
+ current.bold = bold === "1";
803
+ current.italic = italic === "1";
804
+ current.text = collapse(current.text);
805
+ current.words = countWords(current.text);
806
+ current.top = current.y + current.size * 0.8;
807
+ current.bottom = current.y - current.size * 0.2;
808
+ if (current.text) frags.push(current);
809
+ current = null;
810
+ };
811
+ for (const item of row) {
812
+ if (current) {
813
+ const gap = item.x0 - current.x1;
814
+ const em = Math.max(current.size, item.size);
815
+ const markerOnly = MARKER_ONLY_RE.test(collapse(current.text));
816
+ if (gap > em * (markerOnly ? 6 : 1)) finish();
817
+ }
818
+ if (!current) {
819
+ current = {
820
+ text: item.text,
821
+ x0: item.x0,
822
+ x1: item.x1,
823
+ y: item.y,
824
+ top: 0,
825
+ bottom: 0,
826
+ size: item.size,
827
+ bold: item.bold,
828
+ italic: item.italic,
829
+ words: 0,
830
+ styleChars: /* @__PURE__ */ new Map()
831
+ };
832
+ } else {
833
+ const gap = item.x0 - current.x1;
834
+ if (gap > Math.max(current.size, item.size) * 0.15 && !/\s$/.test(current.text) && !/^\s/.test(item.text)) {
835
+ current.text += " ";
836
+ }
837
+ current.text += item.text;
838
+ current.x1 = Math.max(current.x1, item.x1);
839
+ }
840
+ const key = `${Math.round(item.size * 2) / 2}|${item.bold ? 1 : 0}|${item.italic ? 1 : 0}`;
841
+ current.styleChars.set(key, (current.styleChars.get(key) ?? 0) + item.text.trim().length);
842
+ }
843
+ finish();
844
+ }
845
+ return frags;
846
+ }
847
+ function baselineRows(frags) {
848
+ const rows = [];
849
+ for (const frag of frags) {
850
+ const row = rows[rows.length - 1];
851
+ if (row && Math.abs(row[0].y - frag.y) <= Math.max(1, Math.min(row[0].size, frag.size) * 0.5)) row.push(frag);
852
+ else rows.push([frag]);
853
+ }
854
+ return rows;
855
+ }
856
+ var edgeKey = (row) => collapse(row.map((f) => f.text).join(" ")).toLowerCase().replace(/\d+/g, "#");
857
+ function removeHeadersAndFooters(pages) {
858
+ const removed = { headers: 0, footers: 0, pageNumbers: 0 };
859
+ const pageRows = pages.map((frags) => baselineRows([...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0)));
860
+ const counts = /* @__PURE__ */ new Map();
861
+ const candidates = [];
862
+ pageRows.forEach((rows, page) => {
863
+ const n = rows.length;
864
+ const picks = [];
865
+ for (let k = 0; k < Math.min(2, n); k++) picks.push([k, "top"]);
866
+ for (let k = Math.max(Math.min(2, n), n - 2); k < n; k++) picks.push([k, "bottom"]);
867
+ for (const [index, edge] of picks) {
868
+ const row = rows[index];
869
+ const extreme = edge === "top" ? index === 0 : index === n - 1;
870
+ const neighbour = edge === "top" ? rows[index + 1] : rows[index - 1];
871
+ const gap = neighbour ? Math.abs(row[0].y - neighbour[0].y) / row[0].size : Infinity;
872
+ candidates.push({ page, row, edge, extreme, gap });
873
+ const key = `${edge}:${edgeKey(row)}`;
874
+ if (!counts.has(key)) counts.set(key, /* @__PURE__ */ new Set());
875
+ counts.get(key).add(page);
876
+ }
877
+ });
878
+ const minPages = Math.max(2, Math.ceil(pages.length * 0.5));
879
+ const drop = /* @__PURE__ */ new Set();
880
+ for (const candidate of candidates) {
881
+ const text = collapse(candidate.row.map((f) => f.text).join(" "));
882
+ const isPageNumber = candidate.extreme && (PAGE_NUMBER_RE.test(text) || DASHED_PAGE_NUMBER_RE.test(text));
883
+ const repeated = (counts.get(`${candidate.edge}:${edgeKey(candidate.row)}`)?.size ?? 0) >= minPages;
884
+ let kind = null;
885
+ if (isPageNumber && (pages.length > 1 || candidate.gap > 2.5)) kind = "pageNumbers";
886
+ else if (repeated && pages.length > 1) kind = candidate.edge === "top" ? "headers" : "footers";
887
+ if (!kind || candidate.row.some((f) => drop.has(f))) continue;
888
+ candidate.row.forEach((f) => drop.add(f));
889
+ removed[kind]++;
890
+ }
891
+ if (drop.size) {
892
+ pages.forEach((frags, index) => {
893
+ pages[index] = frags.filter((f) => !drop.has(f));
894
+ });
895
+ }
896
+ return removed;
897
+ }
898
+ function splitRules(rules) {
899
+ const h = [];
900
+ const v = [];
901
+ for (const rule of rules.slice(0, MAX_RULES)) {
902
+ const { x1, y1, x2, y2 } = rule;
903
+ if (![x1, y1, x2, y2].every(Number.isFinite)) continue;
904
+ const dx = Math.abs(x2 - x1);
905
+ const dy = Math.abs(y2 - y1);
906
+ if (dy <= 1.5 && dx >= 6) h.push({ y: (y1 + y2) / 2, x0: Math.min(x1, x2), x1: Math.max(x1, x2) });
907
+ else if (dx <= 1.5 && dy >= 6) v.push({ x: (x1 + x2) / 2, y0: Math.min(y1, y2), y1: Math.max(y1, y2) });
908
+ }
909
+ return { h, v };
910
+ }
911
+ function clusterValues(values, tol) {
912
+ const sorted = [...values].sort((a, b) => a - b);
913
+ const out = [];
914
+ for (const value of sorted) {
915
+ const cluster = out[out.length - 1];
916
+ if (cluster && value - cluster.last <= tol) {
917
+ cluster.sum += value;
918
+ cluster.n++;
919
+ cluster.last = value;
920
+ } else out.push({ sum: value, n: 1, last: value });
921
+ }
922
+ return out.map((c) => c.sum / c.n);
923
+ }
924
+ function find(parent, i) {
925
+ while (parent[i] !== i) {
926
+ parent[i] = parent[parent[i]];
927
+ i = parent[i];
928
+ }
929
+ return i;
930
+ }
931
+ var cellText = (frags, dehyphenate, stats) => {
932
+ const sorted = [...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0);
933
+ let text = "";
934
+ let lastY = Infinity;
935
+ for (const frag of sorted) {
936
+ if (!text) text = frag.text;
937
+ else if (Math.abs(lastY - frag.y) > frag.size * 0.5) text = joinLines(text, frag.text, dehyphenate, stats);
938
+ else text += ` ${frag.text}`;
939
+ lastY = frag.y;
940
+ }
941
+ return collapse(text);
942
+ };
943
+ var NUMERIC_RE = /^[-+−(]?[$€£¥]?\s?\d[\d,.\s]*%?\)?$/;
944
+ function headerRowCount(rowFrags) {
945
+ if (rowFrags.length < 2) return 0;
946
+ const cells = (row) => row.filter((cell) => cell.length > 0);
947
+ const first = cells(rowFrags[0]);
948
+ if (!first.length) return 0;
949
+ const rest = rowFrags.slice(1).flatMap(cells);
950
+ const allBold = (list) => list.length > 0 && list.every((cell) => cell.every((f) => f.bold));
951
+ if (allBold(first) && !allBold(rest)) return 1;
952
+ const numeric = (cell) => NUMERIC_RE.test(collapse(cell.map((f) => f.text).join(" ")));
953
+ if (first.every((cell) => !numeric(cell))) {
954
+ const columns = rowFrags[0].length;
955
+ for (let c = 0; c < columns; c++) {
956
+ const body = rowFrags.slice(1).map((row) => row[c]).filter((cell) => cell && cell.length > 0);
957
+ if (rowFrags[0][c].length && body.length >= 2 && body.every(numeric)) return 1;
958
+ }
959
+ }
960
+ const firstSize = maxOf(first.flat(), (f) => f.size);
961
+ const restSize = median(rest.flat().map((f) => f.size));
962
+ if (restSize > 0 && firstSize >= restSize * 1.1) return 1;
963
+ return 0;
964
+ }
965
+ function ruledTables(frags, rules, page, dehyphenate, stats) {
966
+ const consumed = /* @__PURE__ */ new Set();
967
+ const atoms = [];
968
+ const { h, v } = splitRules(rules);
969
+ if (h.length < 2) return { atoms, consumed };
970
+ const n = h.length + v.length;
971
+ const parent = Array.from({ length: n }, (_, i) => i);
972
+ const union = (a, b) => {
973
+ const ra = find(parent, a);
974
+ const rb = find(parent, b);
975
+ if (ra !== rb) parent[ra] = rb;
976
+ };
977
+ const tol = 2;
978
+ const vOrder = v.map((_, i) => i).sort((a, b) => v[a].x - v[b].x);
979
+ const vxs = vOrder.map((i) => v[i].x);
980
+ h.forEach((seg, hi) => {
981
+ let lo = 0;
982
+ let hiIdx = vxs.length;
983
+ while (lo < hiIdx) {
984
+ const mid = lo + hiIdx >> 1;
985
+ if (vxs[mid] < seg.x0 - tol) lo = mid + 1;
986
+ else hiIdx = mid;
987
+ }
988
+ for (let k = lo; k < vxs.length && vxs[k] <= seg.x1 + tol; k++) {
989
+ const vs = v[vOrder[k]];
990
+ if (seg.y >= vs.y0 - tol && seg.y <= vs.y1 + tol) union(hi, h.length + vOrder[k]);
991
+ }
992
+ });
993
+ const hOrder = h.map((_, i) => i).sort((a, b) => h[a].x0 - h[b].x0 || h[a].x1 - h[b].x1 || h[b].y - h[a].y);
994
+ for (let k = 1; k < hOrder.length; k++) {
995
+ const a = h[hOrder[k - 1]];
996
+ const b = h[hOrder[k]];
997
+ if (Math.abs(a.x0 - b.x0) <= 4 && Math.abs(a.x1 - b.x1) <= 4) union(hOrder[k - 1], hOrder[k]);
998
+ }
999
+ const groups = /* @__PURE__ */ new Map();
1000
+ h.forEach((seg, i) => {
1001
+ const root = find(parent, i);
1002
+ if (!groups.has(root)) groups.set(root, { h: [], v: [] });
1003
+ groups.get(root).h.push(seg);
1004
+ });
1005
+ v.forEach((seg, i) => {
1006
+ const root = find(parent, h.length + i);
1007
+ groups.get(root)?.v.push(seg);
1008
+ });
1009
+ const byY = [...frags].sort((a, b) => a.y - b.y);
1010
+ const ys = byY.map((f) => f.y);
1011
+ const inRange = (y0, y1) => {
1012
+ let lo = 0;
1013
+ let hi = ys.length;
1014
+ while (lo < hi) {
1015
+ const mid = lo + hi >> 1;
1016
+ if (ys[mid] < y0) lo = mid + 1;
1017
+ else hi = mid;
1018
+ }
1019
+ const out = [];
1020
+ for (let k = lo; k < ys.length && ys[k] <= y1; k++) out.push(byY[k]);
1021
+ return out;
1022
+ };
1023
+ groups.forEach((group) => {
1024
+ const hys = clusterValues(group.h.map((s) => s.y), 1.5).sort((a, b) => b - a);
1025
+ if (hys.length < 2) return;
1026
+ const x0 = Math.min(...group.h.map((s) => s.x0), ...group.v.map((s) => s.x));
1027
+ const x1 = Math.max(...group.h.map((s) => s.x1), ...group.v.map((s) => s.x));
1028
+ const top = Math.max(hys[0], ...group.v.map((s) => s.y1));
1029
+ const bottom = Math.min(hys[hys.length - 1], ...group.v.map((s) => s.y0));
1030
+ const inside = inRange(bottom, top).filter((f) => {
1031
+ if (consumed.has(f)) return false;
1032
+ const cx = (f.x0 + f.x1) / 2;
1033
+ return cx >= x0 - 1 && cx <= x1 + 1;
1034
+ });
1035
+ if (inside.length < 2) return;
1036
+ const vxsGroup = clusterValues(group.v.map((s) => s.x), 1.5);
1037
+ let table = null;
1038
+ if (vxsGroup.length >= 3 || vxsGroup.length >= 2 && hys.length >= 3 && vxsGroup.some((x) => x > x0 + 4 && x < x1 - 4)) {
1039
+ table = gridTable(inside, group, hys, vxsGroup, x0, x1, top, bottom, page, dehyphenate, stats);
1040
+ }
1041
+ if (!table) {
1042
+ const result = alignedTable(inside, page, 2, dehyphenate, stats, hys.length >= 3 ? hys[1] : void 0);
1043
+ if (result && !result.leftover.length && !result.before.length) table = { ...result.table, ruled: true, confidence: 0.85 };
1044
+ }
1045
+ if (!table) return;
1046
+ inside.forEach((f) => consumed.add(f));
1047
+ atoms.push({
1048
+ text: "",
1049
+ x0,
1050
+ x1,
1051
+ y: bottom,
1052
+ top,
1053
+ bottom,
1054
+ size: median(inside.map((f) => f.size)),
1055
+ bold: false,
1056
+ italic: false,
1057
+ words: 0,
1058
+ table
1059
+ });
1060
+ });
1061
+ return { atoms, consumed };
1062
+ }
1063
+ function gridTable(inside, group, hys, vxsIn, x0, x1, top, bottom, page, dehyphenate, stats) {
1064
+ const xs = [...vxsIn];
1065
+ if (xs[0] > x0 + 4) xs.unshift(x0);
1066
+ if (xs[xs.length - 1] < x1 - 4) xs.push(x1);
1067
+ const rowsY = [...hys];
1068
+ if (rowsY[0] < top - 4) rowsY.unshift(top);
1069
+ if (rowsY[rowsY.length - 1] > bottom + 4) rowsY.push(bottom);
1070
+ const cols = xs.length - 1;
1071
+ const rows = rowsY.length - 1;
1072
+ if (cols < 2 || rows < 1 || cols > MAX_COLS || rows > MAX_TABLE_ROWS) return null;
1073
+ const grid = Array.from({ length: rows }, () => Array.from({ length: cols }, () => []));
1074
+ const ascRows = [...rowsY].reverse();
1075
+ for (const frag of inside) {
1076
+ const x = frag.x0 + Math.min(2, (frag.x1 - frag.x0) / 2);
1077
+ const c = lowerBound(xs, x + 1e-9) - 1;
1078
+ const yProbe = frag.y + frag.size * 0.3;
1079
+ const r = rows - (lowerBound(ascRows, yProbe + 1e-9) - 1) - 1;
1080
+ if (c >= 0 && c < cols && r >= 0 && r < rows) grid[r][c].push(frag);
1081
+ }
1082
+ const filled = grid.flat().filter((cell) => cell.length).length;
1083
+ if (filled < 2 || rows < 2 && cols < 2) return null;
1084
+ const vAt = xs.map(() => []);
1085
+ for (const seg of group.v) {
1086
+ const k = lowerBound(xs, seg.x - 2);
1087
+ if (k < xs.length && Math.abs(xs[k] - seg.x) <= 2) vAt[k].push(seg);
1088
+ }
1089
+ const hAt = rowsY.map(() => []);
1090
+ for (const seg of group.h) {
1091
+ const k = rows - lowerBound(ascRows, seg.y - 2);
1092
+ if (k >= 0 && k <= rows && Math.abs(rowsY[k] - seg.y) <= 2) hAt[k].push(seg);
1093
+ }
1094
+ const hasV = (k, y) => vAt[k].some((s) => y >= s.y0 - 2 && y <= s.y1 + 2);
1095
+ const hasH = (k, x) => hAt[k].some((s) => x >= s.x0 - 2 && x <= s.x1 + 2);
1096
+ const covered = grid.map((row) => row.map(() => false));
1097
+ const header = headerRowCount(grid);
1098
+ const out = [];
1099
+ for (let r = 0; r < rows; r++) {
1100
+ const midY = (rowsY[r] + rowsY[r + 1]) / 2;
1101
+ const row = [];
1102
+ for (let c = 0; c < cols; c++) {
1103
+ if (covered[r][c]) continue;
1104
+ let colSpan = 1;
1105
+ while (c + colSpan < cols && !hasV(c + colSpan, midY) && !grid[r][c + colSpan].length && !covered[r][c + colSpan]) colSpan++;
1106
+ let rowSpan = 1;
1107
+ const midX = (xs[c] + xs[c + colSpan]) / 2;
1108
+ while (r + rowSpan < rows && !hasH(r + rowSpan, midX) && !covered[r + rowSpan].slice(c, c + colSpan).some(Boolean) && grid[r + rowSpan].slice(c, c + colSpan).every((cell) => !cell.length)) {
1109
+ rowSpan++;
1110
+ }
1111
+ for (let rr = r; rr < r + rowSpan; rr++) for (let cc = c; cc < c + colSpan; cc++) covered[rr][cc] = true;
1112
+ row.push({ text: cellText(grid[r][c], dehyphenate, stats), colSpan, rowSpan, header: r < header });
1113
+ }
1114
+ out.push(row);
1115
+ }
1116
+ return { type: "table", page, confidence: 0.95, ruled: true, rows: out, columns: cols, headerRows: header };
1117
+ }
1118
+ function alignedTable(frags, page, minRows, dehyphenate, stats, headerRuleY) {
1119
+ const sorted = [...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0);
1120
+ let rows = baselineRows(sorted).map((row) => row.sort((a, b) => a.x0 - b.x0));
1121
+ if (rows.length < minRows) return null;
1122
+ const multi = rows.filter((row) => row.length >= 2);
1123
+ if (multi.length < Math.min(minRows, 2)) return null;
1124
+ const spans = multi.flat().map((f) => [f.x0, f.x1]).sort((a, b) => a[0] - b[0]);
1125
+ const merged = [];
1126
+ for (const [a, b] of spans) {
1127
+ const last = merged[merged.length - 1];
1128
+ if (last && a <= last[1] + 1) last[1] = Math.max(last[1], b);
1129
+ else merged.push([a, b]);
1130
+ }
1131
+ if (merged.length < 2 || merged.length > MAX_COLS) return null;
1132
+ const edges = merged.map((m) => m[0]);
1133
+ const cols = merged.length;
1134
+ const colOf = (x) => {
1135
+ let c = 0;
1136
+ while (c + 1 < cols && x >= merged[c + 1][0] - 1) c++;
1137
+ return c;
1138
+ };
1139
+ const spanOf = (f, c) => {
1140
+ let span = 1;
1141
+ while (c + span < cols && f.x1 > merged[c + span][0] + 2) span++;
1142
+ return span;
1143
+ };
1144
+ const rowIsCells = (row) => {
1145
+ if (row.length >= 2) return true;
1146
+ const f = row[0];
1147
+ const c = colOf(f.x0);
1148
+ return spanOf(f, c) >= 2 && f.words <= 8 && Math.abs(f.x0 - edges[c]) <= Math.max(4, f.size * 0.6);
1149
+ };
1150
+ const before = [];
1151
+ const leftover = [];
1152
+ let first = 0;
1153
+ let end = rows.length;
1154
+ while (first < end && !rowIsCells(rows[first])) first++;
1155
+ while (end > first && !rowIsCells(rows[end - 1])) end--;
1156
+ rows.slice(0, first).forEach((row) => before.push(...row));
1157
+ rows.slice(end).forEach((row) => leftover.push(...row));
1158
+ rows = rows.slice(first, end);
1159
+ if (rows.length < minRows || rows.length > MAX_TABLE_ROWS) return null;
1160
+ const grid = [];
1161
+ const spansGrid = [];
1162
+ let prevRow = null;
1163
+ for (const row of rows) {
1164
+ const cells = Array.from({ length: cols }, () => []);
1165
+ const spanRow = Array.from({ length: cols }, () => 1);
1166
+ for (const f of row) {
1167
+ const c = colOf(f.x0);
1168
+ cells[c].push(f);
1169
+ spanRow[c] = Math.max(spanRow[c], row.length === 1 ? spanOf(f, c) : 1);
1170
+ }
1171
+ const continuation = prevRow !== null && grid.length > 0 && cells[0].length === 0 && grid[grid.length - 1][0].length > 0 && cells.every((cell, c) => !cell.length || grid[grid.length - 1][c].length > 0) && minOf(prevRow, (f) => f.bottom) - maxOf(row, (f) => f.top) < row[0].size * 0.5;
1172
+ if (continuation) {
1173
+ cells.forEach((cell, c) => grid[grid.length - 1][c].push(...cell));
1174
+ } else {
1175
+ grid.push(cells);
1176
+ spansGrid.push(spanRow);
1177
+ }
1178
+ prevRow = row;
1179
+ }
1180
+ if (grid.length < minRows) return null;
1181
+ const full = grid.filter((cells) => cells.filter((c) => c.length).length >= 2).length;
1182
+ if (full / grid.length < 0.6) return null;
1183
+ const cellsWithText = grid.flat().filter((c) => c.length);
1184
+ const meanWords = cellsWithText.reduce((sum, cell) => sum + cell.reduce((s, f) => s + f.words, 0), 0) / cellsWithText.length;
1185
+ if (meanWords > 12) return null;
1186
+ let header = headerRowCount(grid);
1187
+ if (headerRuleY !== void 0) {
1188
+ const above = rows.filter((row) => row[0].y > headerRuleY).length;
1189
+ if (above > 0 && above < grid.length) header = Math.max(header, Math.min(above, grid.length - 1));
1190
+ }
1191
+ const out = grid.map((cells, r) => {
1192
+ const row = [];
1193
+ for (let c = 0; c < cols; ) {
1194
+ const span = Math.min(spansGrid[r][c], cols - c);
1195
+ row.push({ text: cellText(cells[c], dehyphenate, stats), colSpan: span, rowSpan: 1, header: r < header });
1196
+ c += span;
1197
+ }
1198
+ return row;
1199
+ });
1200
+ const confidence = Math.min(
1201
+ 0.9,
1202
+ 0.5 + (grid.length >= 5 ? 0.1 : 0) + (cols >= 3 ? 0.1 : 0) + 0.2 * (full / grid.length) - (cols === 2 ? 0.05 : 0)
1203
+ );
1204
+ return {
1205
+ table: { type: "table", page, confidence, ruled: false, rows: out, columns: cols, headerRows: header },
1206
+ leftover,
1207
+ before
1208
+ };
1209
+ }
1210
+ function readingOrder(items, body, detectColumns, depth, columnPages) {
1211
+ const byTop = [...items].sort((a, b) => b.top - a.top || a.x0 - b.x0);
1212
+ if (!detectColumns || items.length < 2 || depth > MAX_DEPTH) return [{ kind: "flow", items: byTop }];
1213
+ const left = minOf(items, (f) => f.x0);
1214
+ const right = maxOf(items, (f) => f.x1);
1215
+ const width = right - left;
1216
+ const isNarrow = (f) => f.x1 - f.x0 < width * 0.55;
1217
+ const narrow = items.filter(isNarrow);
1218
+ const minGutter = Math.max(body * 0.9, 6);
1219
+ const allowed = Math.max(1, Math.floor(narrow.length * 0.08));
1220
+ const events = [];
1221
+ for (const f of narrow) events.push([f.x0, 1], [f.x1, -1]);
1222
+ events.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
1223
+ const candidates = [];
1224
+ let depthNow = 0;
1225
+ let seenContent = false;
1226
+ let start = null;
1227
+ for (const [x, delta] of events) {
1228
+ depthNow += delta;
1229
+ if (depthNow > allowed) {
1230
+ if (start !== null && seenContent && x - start >= minGutter) candidates.push([start, x]);
1231
+ start = null;
1232
+ seenContent = true;
1233
+ } else if (start === null) start = x;
1234
+ }
1235
+ const ends = narrow.map((f) => f.x1).sort((a, b) => a - b);
1236
+ const starts = narrow.map((f) => f.x0).sort((a, b) => a - b);
1237
+ const gutters = [];
1238
+ for (const [a, b] of candidates) {
1239
+ const endBelow = lowerBound(ends, b) - 1;
1240
+ const left2 = endBelow >= 0 && ends[endBelow] > a ? ends[endBelow] : a;
1241
+ const startAbove = lowerBound(starts, a + 1e-9);
1242
+ const right2 = startAbove < starts.length && starts[startAbove] < b ? starts[startAbove] : b;
1243
+ if (right2 - left2 < minGutter) continue;
1244
+ const onLeft = lowerBound(ends, left2 + 1e-6);
1245
+ const onRight = starts.length - lowerBound(starts, right2 - 1e-6);
1246
+ const strays = narrow.length - onLeft - onRight;
1247
+ if (strays < Math.min(onLeft, onRight)) gutters.push([left2, right2]);
1248
+ }
1249
+ if (!gutters.length) return [{ kind: "flow", items: byTop }];
1250
+ const gutterEnds = gutters.map((g) => g[1]);
1251
+ const crosses = (f) => {
1252
+ const k = lowerBound(gutterEnds, f.x0 + 1 + 1e-9);
1253
+ return k < gutters.length && f.x1 > gutters[k][0] + 1 && f.x0 < gutters[k][1] - 1;
1254
+ };
1255
+ const columnOf = (f) => lowerBound(gutterEnds, f.x0 + 1 + 1e-9);
1256
+ const bands = [];
1257
+ for (const f of byTop) {
1258
+ const spanning = crosses(f);
1259
+ const band = bands[bands.length - 1];
1260
+ if (band && band.spanning === spanning) band.items.push(f);
1261
+ else bands.push({ spanning, items: [f] });
1262
+ }
1263
+ const segments = [];
1264
+ let sealed = false;
1265
+ const pushFlow = (list) => {
1266
+ if (!list.length) return;
1267
+ const last = segments[segments.length - 1];
1268
+ if (last && last.kind === "flow" && !sealed) last.items.push(...list);
1269
+ else segments.push({ kind: "flow", items: list });
1270
+ sealed = false;
1271
+ };
1272
+ let multiColumn = false;
1273
+ const isShortSpan = (f) => !f.table && isNarrow(f) && f.words <= 8;
1274
+ for (const band of bands) {
1275
+ const last = segments[segments.length - 1];
1276
+ if (band.spanning) {
1277
+ const lead = band.items[0];
1278
+ if (last && last.kind === "grid" && isShortSpan(lead) && minOf(last.items, (f) => f.bottom) - lead.top <= lead.size * 2) {
1279
+ last.items.push(lead);
1280
+ pushFlow(band.items.slice(1));
1281
+ } else pushFlow(band.items);
1282
+ continue;
1283
+ }
1284
+ const columns = Array.from({ length: gutters.length + 1 }, () => []);
1285
+ band.items.forEach((f) => columns[columnOf(f)].push(f));
1286
+ const used = columns.filter((c) => c.length);
1287
+ if (used.length < 2) {
1288
+ pushFlow(band.items);
1289
+ continue;
1290
+ }
1291
+ const prose = used.every((col) => {
1292
+ const text = col.filter((f) => !f.table);
1293
+ if (text.length < 2) return text.length === 0;
1294
+ const colLeft = minOf(text, (f) => f.x0);
1295
+ const colRight = maxOf(text, (f) => f.x1);
1296
+ const fill = text.reduce((sum, f) => sum + (f.x1 - f.x0), 0) / text.length / Math.max(1, colRight - colLeft);
1297
+ const words = text.reduce((sum, f) => sum + f.words, 0) / text.length;
1298
+ return fill >= 0.55 && words >= 3;
1299
+ });
1300
+ const tops = used.map((col) => [minOf(col, (f) => f.bottom), maxOf(col, (f) => f.top)]);
1301
+ const overlapping = tops.every(([b, t], i) => i === 0 || Math.min(t, tops[0][1]) - Math.max(b, tops[0][0]) > 0);
1302
+ if (prose && overlapping) {
1303
+ multiColumn = true;
1304
+ for (const col of used) segments.push(...readingOrder(col, body, detectColumns, depth + 1, columnPages));
1305
+ sealed = true;
1306
+ continue;
1307
+ }
1308
+ const pulled = [];
1309
+ if (last && last.kind === "flow" && !sealed) {
1310
+ const tail = last.items[last.items.length - 1];
1311
+ if (isShortSpan(tail) && tail.bottom - maxOf(band.items, (f) => f.top) <= tail.size * 2) {
1312
+ pulled.push(last.items.pop());
1313
+ if (!last.items.length) segments.pop();
1314
+ }
1315
+ }
1316
+ const prevSegment = segments[segments.length - 1];
1317
+ if (prevSegment && prevSegment.kind === "grid" && (pulled.length || prevSegment === last)) {
1318
+ prevSegment.items.push(...pulled, ...band.items);
1319
+ } else segments.push({ kind: "grid", items: [...pulled, ...band.items] });
1320
+ sealed = false;
1321
+ }
1322
+ if (multiColumn && depth === 0) columnPages.count++;
1323
+ return segments;
1324
+ }
1325
+ function flowLines(items, page) {
1326
+ const lines = [];
1327
+ const sorted = [...items].sort((a, b) => b.top - a.top || a.x0 - b.x0);
1328
+ for (const f of sorted) {
1329
+ if (f.table) {
1330
+ lines.push({ text: "", x0: f.x0, x1: f.x1, y: f.y, top: f.top, size: f.size, bold: false, page, table: f.table });
1331
+ continue;
1332
+ }
1333
+ const last = lines[lines.length - 1];
1334
+ if (last && !last.table && Math.abs(last.y - f.y) <= Math.min(last.size, f.size) * 0.5) {
1335
+ last.text = `${last.text} ${f.text}`;
1336
+ last.x0 = Math.min(last.x0, f.x0);
1337
+ last.x1 = Math.max(last.x1, f.x1);
1338
+ } else {
1339
+ lines.push({ text: f.text, x0: f.x0, x1: f.x1, y: f.y, top: f.top, size: f.size, bold: f.bold, page });
1340
+ }
1341
+ }
1342
+ return lines;
1343
+ }
1344
+ function joinLines(prev, next, dehyphenate, stats) {
1345
+ if (prev.endsWith("\xAD")) {
1346
+ stats.dehyphenated++;
1347
+ return prev.slice(0, -1) + next;
1348
+ }
1349
+ if (dehyphenate && /[A-Za-zÀ-ɏ]-$/.test(prev) && /^[a-zß-ɏ]/.test(next)) {
1350
+ stats.dehyphenated++;
1351
+ return prev.slice(0, -1) + next;
1352
+ }
1353
+ return `${prev} ${next}`;
1354
+ }
1355
+ function listMarker(text) {
1356
+ const glyph = BULLET_GLYPH_RE.exec(text);
1357
+ if (glyph) return { kind: "glyph", rest: text.slice(glyph[0].length), ordered: false };
1358
+ const dash = BULLET_DASH_RE.exec(text);
1359
+ if (dash) return { kind: "dash", rest: text.slice(dash[0].length), ordered: false };
1360
+ const ordered = ORDERED_RE.exec(text);
1361
+ if (ordered) {
1362
+ const token = ordered[1] ?? ordered[2];
1363
+ const kind = /^\d+$/.test(token) ? "num" : /^[ivxlc]{2,}$/i.test(token) || /^i$/i.test(token) ? "roman" : "alpha";
1364
+ return { kind, rest: text.slice(ordered[0].length), ordered: true, value: kind === "num" ? Number(token) : void 0 };
1365
+ }
1366
+ return null;
1367
+ }
1368
+ function headingStyle(line, next, segRight, ctx) {
1369
+ if (!ctx.options.detectHeadings || line.table) return null;
1370
+ const text = line.text;
1371
+ const words = countWords(text);
1372
+ if (text.length > 200 || words > 25 || !/\p{L}/u.test(text)) return null;
1373
+ if (words > 15 && SENTENCE_END_RE.test(text)) return null;
1374
+ const ratio = line.size / ctx.body;
1375
+ if (ratio >= 1.15) {
1376
+ const confidence = Math.min(0.95, 0.6 + (ratio - 1.15) * 0.8 + (line.bold ? 0.1 : 0));
1377
+ return { key: Math.round(line.size * 2) / 2 + (line.bold ? 0.25 : 0), confidence, boldOnly: false };
1378
+ }
1379
+ const runsOn = !!next && !next.table && next.bold && Math.abs(next.size - line.size) < 0.5 && line.x1 >= segRight - 2 * line.size;
1380
+ if (line.bold && !ctx.boldBody && !runsOn && ratio >= 0.95 && text.length <= 100 && !/[.,;]$/.test(text)) {
1381
+ return { key: Math.round(line.size * 2) / 2 + 0.25, confidence: 0.6, boldOnly: true };
1382
+ }
1383
+ return null;
1384
+ }
1385
+ function buildBlocks(lines, ctx) {
1386
+ const textLines = lines.filter((l) => !l.table);
1387
+ const segLeft = textLines.length ? minOf(textLines, (l) => l.x0) : 0;
1388
+ const segRight = textLines.length ? maxOf(textLines, (l) => l.x1) : 0;
1389
+ const kindCounts = /* @__PURE__ */ new Map();
1390
+ const markers = lines.map((line) => {
1391
+ if (!ctx.options.detectLists || line.table) return null;
1392
+ const marker = listMarker(line.text);
1393
+ if (marker) kindCounts.set(marker.kind, (kindCounts.get(marker.kind) ?? 0) + 1);
1394
+ return marker;
1395
+ });
1396
+ let list = null;
1397
+ let listStack = [];
1398
+ let lastItemLine = null;
1399
+ let para = null;
1400
+ let heading = null;
1401
+ const closeAll = () => {
1402
+ if (para) {
1403
+ const last = para.lines[para.lines.length - 1];
1404
+ const ended = SENTENCE_END_RE.test(last.text) || last.x1 < segRight - 3 * last.size;
1405
+ ctx.open = ended ? null : { block: para.block, size: last.size, lastText: para.block.text };
1406
+ } else ctx.open = null;
1407
+ para = null;
1408
+ list = null;
1409
+ listStack = [];
1410
+ lastItemLine = null;
1411
+ heading = null;
1412
+ };
1413
+ lines.forEach((line, index) => {
1414
+ const prev = index > 0 ? lines[index - 1] : null;
1415
+ if (line.table) {
1416
+ closeAll();
1417
+ ctx.open = null;
1418
+ ctx.blocks.push(line.table);
1419
+ return;
1420
+ }
1421
+ const style = headingStyle(line, lines[index + 1], segRight, ctx);
1422
+ if (style) {
1423
+ if (heading && heading.key === style.key && heading.lines < 3 && prev === heading.line && prev.y - line.y <= line.size * 1.6) {
1424
+ heading.block.text = joinLines(heading.block.text, line.text, ctx.options.dehyphenate, ctx.stats);
1425
+ heading.line = line;
1426
+ heading.lines++;
1427
+ return;
1428
+ }
1429
+ closeAll();
1430
+ ctx.open = null;
1431
+ const block2 = { type: "heading", level: 1, text: line.text, page: line.page, confidence: style.confidence };
1432
+ ctx.blocks.push(block2);
1433
+ ctx.headings.push({ block: block2, key: style.key, boldOnly: style.boldOnly });
1434
+ heading = { block: block2, line, key: style.key, lines: 1 };
1435
+ return;
1436
+ }
1437
+ heading = null;
1438
+ const marker = markers[index];
1439
+ const validMarker = marker && (marker.kind === "glyph" || (kindCounts.get(marker.kind) ?? 0) >= 2) && marker.rest.trim() !== "";
1440
+ if (validMarker) {
1441
+ const gapOk = lastItemLine && lastItemLine.y - line.y <= Math.max(ctx.pitch(line.size) * 2.2, line.size * 2.4);
1442
+ if (!list || !gapOk) {
1443
+ closeAll();
1444
+ ctx.open = null;
1445
+ list = { type: "list", page: line.page, confidence: 0.6, items: [] };
1446
+ ctx.blocks.push(list);
1447
+ listStack = [line.x0];
1448
+ }
1449
+ const tol = line.size * 0.5;
1450
+ while (listStack.length > 1 && line.x0 < listStack[listStack.length - 1] - tol) listStack.pop();
1451
+ if (line.x0 > listStack[listStack.length - 1] + tol) listStack.push(line.x0);
1452
+ else listStack[listStack.length - 1] = Math.min(listStack[listStack.length - 1], line.x0);
1453
+ const prevDepth = list.items.length ? list.items[list.items.length - 1].depth : -1;
1454
+ const depth = Math.min(listStack.length - 1, prevDepth + 1);
1455
+ const item = {
1456
+ text: collapse(marker.rest),
1457
+ depth,
1458
+ ordered: marker.ordered
1459
+ };
1460
+ if (marker.value !== void 0) item.start = marker.value;
1461
+ list.items.push(item);
1462
+ list.confidence = Math.min(0.95, (marker.kind === "glyph" ? 0.75 : 0.6) + 0.05 * list.items.length);
1463
+ lastItemLine = line;
1464
+ para = null;
1465
+ return;
1466
+ }
1467
+ if (list && lastItemLine && prev) {
1468
+ const markerX = listStack[listStack.length - 1];
1469
+ const continues = line.x0 > markerX + line.size * 0.3 && line.x0 <= markerX + line.size * 5 && prev.y - line.y <= ctx.pitch(line.size) * ctx.options.paragraphGap;
1470
+ if (continues) {
1471
+ const item = list.items[list.items.length - 1];
1472
+ item.text = joinLines(item.text, line.text, ctx.options.dehyphenate, ctx.stats);
1473
+ lastItemLine = line;
1474
+ return;
1475
+ }
1476
+ closeAll();
1477
+ }
1478
+ if (!para && ctx.open && index === 0 && /^[a-z]/.test(line.text) && Math.abs(ctx.open.size - line.size) <= line.size * 0.12) {
1479
+ ctx.open.block.text = joinLines(ctx.open.block.text, line.text, ctx.options.dehyphenate, ctx.stats);
1480
+ para = { block: ctx.open.block, lines: [line] };
1481
+ ctx.open = null;
1482
+ return;
1483
+ }
1484
+ if (para && prev && !prev.table) {
1485
+ const last = para.lines[para.lines.length - 1];
1486
+ const gap = last.y - line.y;
1487
+ const sameSize = Math.abs(last.size - line.size) <= last.size * 0.12;
1488
+ const closeEnough = gap > 0 && gap <= ctx.pitch(line.size) * ctx.options.paragraphGap;
1489
+ const indentEm = line.size * 0.8;
1490
+ const indented = line.x0 - segLeft >= indentEm && last.x0 - segLeft < indentEm && line.x0 - segLeft < line.size * 8;
1491
+ const shortEnded = last.x1 < segRight - 3 * last.size && SENTENCE_END_RE.test(last.text);
1492
+ if (sameSize && closeEnough && !indented && !shortEnded) {
1493
+ para.block.text = joinLines(para.block.text, line.text, ctx.options.dehyphenate, ctx.stats);
1494
+ para.lines.push(line);
1495
+ return;
1496
+ }
1497
+ }
1498
+ closeAll();
1499
+ ctx.open = null;
1500
+ const block = { type: "paragraph", text: line.text, page: line.page };
1501
+ ctx.blocks.push(block);
1502
+ para = { block, lines: [line] };
1503
+ });
1504
+ closeAll();
1505
+ }
1506
+ function assignHeadingLevels(headings) {
1507
+ const keys = Array.from(new Set(headings.map((h) => h.key))).sort((a, b) => b - a);
1508
+ const levelOf = new Map(keys.map((key, i) => [key, Math.min(6, i + 1)]));
1509
+ headings.forEach((h) => {
1510
+ h.block.level = levelOf.get(h.key);
1511
+ });
1512
+ }
1513
+ var DEFAULTS = {
1514
+ paragraphGap: 1.4,
1515
+ removeHeadersAndFooters: true,
1516
+ detectColumns: true,
1517
+ detectHeadings: true,
1518
+ detectLists: true,
1519
+ detectTables: true,
1520
+ dehyphenate: true
1521
+ };
1522
+ function analyzePdfLayout(pages, options = {}) {
1523
+ const opts = { ...DEFAULTS };
1524
+ Object.keys(options).forEach((key) => {
1525
+ if (options[key] !== void 0) opts[key] = options[key];
1526
+ });
1527
+ const fragPages = pages.map((page) => buildFragments(page.runs ?? []));
1528
+ const removed = opts.removeHeadersAndFooters ? removeHeadersAndFooters(fragPages) : { headers: 0, footers: 0, pageNumbers: 0 };
1529
+ const bySize = /* @__PURE__ */ new Map();
1530
+ let boldChars = 0;
1531
+ let totalChars = 0;
1532
+ fragPages.flat().forEach((f) => {
1533
+ const key = Math.round(f.size * 2) / 2;
1534
+ bySize.set(key, (bySize.get(key) ?? 0) + f.text.length);
1535
+ });
1536
+ let body = 10;
1537
+ let bodyChars = -1;
1538
+ bySize.forEach((chars, size) => {
1539
+ if (chars > bodyChars) {
1540
+ body = size;
1541
+ bodyChars = chars;
1542
+ }
1543
+ });
1544
+ fragPages.flat().forEach((f) => {
1545
+ if (Math.abs(f.size - body) <= body * 0.05) {
1546
+ totalChars += f.text.length;
1547
+ if (f.bold) boldChars += f.text.length;
1548
+ }
1549
+ });
1550
+ const pitches = /* @__PURE__ */ new Map();
1551
+ fragPages.forEach((frags) => {
1552
+ const rows = baselineRows([...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0));
1553
+ for (let k = 1; k < rows.length; k++) {
1554
+ const a = rows[k - 1][0];
1555
+ const b = rows[k][0];
1556
+ if (Math.abs(a.size - b.size) > 0.5) continue;
1557
+ const d = a.y - b.y;
1558
+ if (d > 0 && d < a.size * 3) {
1559
+ const key = Math.round(b.size * 2) / 2;
1560
+ if (!pitches.has(key)) pitches.set(key, []);
1561
+ pitches.get(key).push(d);
1562
+ }
1563
+ }
1564
+ });
1565
+ const pitchMedians = /* @__PURE__ */ new Map();
1566
+ pitches.forEach((values, key) => pitchMedians.set(key, median(values)));
1567
+ const stats = { dehyphenated: 0 };
1568
+ const ctx = {
1569
+ body,
1570
+ boldBody: totalChars > 0 && boldChars / totalChars > 0.5,
1571
+ pitch: (size) => {
1572
+ const known = pitchMedians.get(Math.round(size * 2) / 2);
1573
+ return known && known >= size * 0.9 ? known : size * 1.2;
1574
+ },
1575
+ options: opts,
1576
+ stats,
1577
+ blocks: [],
1578
+ headings: [],
1579
+ open: null
1580
+ };
1581
+ const columnPages = { count: 0 };
1582
+ const items = [];
1583
+ fragPages.forEach((frags, pageIndex) => {
1584
+ const page = pageIndex + 1;
1585
+ let flowFrags = frags;
1586
+ const atoms = [];
1587
+ if (opts.detectTables && pages[pageIndex].rules?.length) {
1588
+ const ruled = ruledTables(frags, pages[pageIndex].rules, page, opts.dehyphenate, stats);
1589
+ flowFrags = frags.filter((f) => !ruled.consumed.has(f));
1590
+ atoms.push(...ruled.atoms);
1591
+ }
1592
+ const before = columnPages.count;
1593
+ const segments = readingOrder([...flowFrags, ...atoms], body, opts.detectColumns, 0, columnPages);
1594
+ if (columnPages.count > before) items.push({ type: "columns", page, confidence: 0.8, detail: "multi-column layout" });
1595
+ const units = [];
1596
+ let carry = [];
1597
+ for (const segment of segments) {
1598
+ if (segment.kind === "grid" && opts.detectTables) {
1599
+ const result = alignedTable(segment.items.filter((f) => !f.table), page, 3, opts.dehyphenate, stats);
1600
+ if (result) {
1601
+ const last = units[units.length - 1];
1602
+ if (result.before.length && last && last.kind === "flow") last.items.push(...carry, ...result.before);
1603
+ else if (result.before.length || carry.length) units.push({ kind: "flow", items: [...carry, ...result.before] });
1604
+ units.push({ kind: "table", table: result.table });
1605
+ carry = [...segment.items.filter((f) => f.table), ...result.leftover];
1606
+ continue;
1607
+ }
1608
+ }
1609
+ units.push({ kind: "flow", items: [...carry, ...segment.items] });
1610
+ carry = [];
1611
+ }
1612
+ if (carry.length) units.push({ kind: "flow", items: carry });
1613
+ for (const unit of units) {
1614
+ if (unit.kind === "table") {
1615
+ ctx.open = null;
1616
+ ctx.blocks.push(unit.table);
1617
+ } else buildBlocks(flowLines(unit.items, page), ctx);
1618
+ }
1619
+ });
1620
+ assignHeadingLevels(ctx.headings);
1621
+ const counts = { headings: 0, lists: 0, tables: 0, paragraphs: 0 };
1622
+ const confidences = [];
1623
+ ctx.blocks.forEach((block) => {
1624
+ if (block.type === "heading") {
1625
+ counts.headings++;
1626
+ confidences.push(block.confidence);
1627
+ items.push({ type: "heading", page: block.page, confidence: block.confidence, detail: `H${block.level} "${truncate(block.text)}"` });
1628
+ } else if (block.type === "list") {
1629
+ counts.lists++;
1630
+ confidences.push(block.confidence);
1631
+ const depth = maxOf(block.items, (i) => i.depth) + 1;
1632
+ items.push({
1633
+ type: "list",
1634
+ page: block.page,
1635
+ confidence: block.confidence,
1636
+ detail: `${block.items[0]?.ordered ? "numbered" : "bulleted"} list, ${block.items.length} items${depth > 1 ? `, ${depth} levels` : ""}`
1637
+ });
1638
+ } else if (block.type === "table") {
1639
+ counts.tables++;
1640
+ confidences.push(block.confidence);
1641
+ items.push({
1642
+ type: "table",
1643
+ page: block.page,
1644
+ confidence: block.confidence,
1645
+ detail: `${block.rows.length}\xD7${block.columns} table${block.ruled ? " (ruled)" : ""}${block.headerRows ? ", header row" : ""}`
1646
+ });
1647
+ } else counts.paragraphs++;
1648
+ });
1649
+ items.sort((a, b) => a.page - b.page);
1650
+ return {
1651
+ blocks: ctx.blocks,
1652
+ report: {
1653
+ mode: "structured",
1654
+ pages: pages.length,
1655
+ counts,
1656
+ multiColumnPages: columnPages.count,
1657
+ confidence: confidences.length ? Math.round(confidences.reduce((a, b) => a + b, 0) / confidences.length * 100) / 100 : 1,
1658
+ items,
1659
+ removed,
1660
+ dehyphenated: stats.dehyphenated
1661
+ }
1662
+ };
1663
+ }
1664
+ var truncate = (text) => text.length > 60 ? `${text.slice(0, 57)}\u2026` : text;
1665
+ function listHtml(items) {
1666
+ let html = "";
1667
+ const stack = [];
1668
+ for (const item of items) {
1669
+ const level = item.depth + 1;
1670
+ while (stack.length > level) html += `</li></${stack.pop()}>`;
1671
+ const tag = item.ordered ? "ol" : "ul";
1672
+ if (stack.length === level) {
1673
+ if (stack[stack.length - 1] !== tag) {
1674
+ html += `</li></${stack.pop()}>`;
1675
+ } else html += "</li>";
1676
+ }
1677
+ while (stack.length < level) {
1678
+ const start = item.ordered && item.start !== void 0 && item.start !== 1 ? ` start="${item.start}"` : "";
1679
+ html += `<${tag}${start}>`;
1680
+ stack.push(tag);
1681
+ }
1682
+ html += `<li><p>${escapeHtml(item.text)}</p>`;
1683
+ }
1684
+ while (stack.length) html += `</li></${stack.pop()}>`;
1685
+ return html;
1686
+ }
1687
+ function pdfLayoutBlocksToHtml(blocks) {
1688
+ let html = "";
1689
+ for (const block of blocks) {
1690
+ if (block.type === "heading") html += `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;
1691
+ else if (block.type === "paragraph") html += `<p>${escapeHtml(block.text)}</p>`;
1692
+ else if (block.type === "list") html += listHtml(block.items);
1693
+ else {
1694
+ html += "<table><tbody>";
1695
+ for (const row of block.rows) {
1696
+ html += "<tr>";
1697
+ for (const cell of row) {
1698
+ const tag = cell.header ? "th" : "td";
1699
+ const attrs = `${cell.colSpan > 1 ? ` colspan="${cell.colSpan}"` : ""}${cell.rowSpan > 1 ? ` rowspan="${cell.rowSpan}"` : ""}`;
1700
+ html += `<${tag}${attrs}><p>${escapeHtml(cell.text)}</p></${tag}>`;
1701
+ }
1702
+ html += "</tr>";
1703
+ }
1704
+ html += "</tbody></table>";
1705
+ }
1706
+ }
1707
+ return html || "<p></p>";
1708
+ }
603
1709
 
604
1710
  // src/import/pdf.ts
605
1711
  var isTextItem = (item) => typeof item.str === "string";
606
- function median(values) {
1712
+ function median2(values) {
607
1713
  if (!values.length) return 0;
608
1714
  const sorted = [...values].sort((a, b) => a - b);
609
1715
  const mid = sorted.length >> 1;
@@ -646,7 +1752,7 @@ function pdfTextItemsToParagraphs(items, options = {}) {
646
1752
  const gap = lines[i - 1].y - lines[i].y;
647
1753
  if (gap > 0) gaps.push(gap);
648
1754
  }
649
- const typical = median(gaps);
1755
+ const typical = median2(gaps);
650
1756
  const factor = options.paragraphGap ?? 1.4;
651
1757
  const paragraphs = [];
652
1758
  let current = [];
@@ -673,6 +1779,228 @@ function pdfTextItemsToParagraphs(items, options = {}) {
673
1779
  flush();
674
1780
  return paragraphs;
675
1781
  }
1782
+ function pdfTextItemsToRuns(items, font) {
1783
+ const runs = [];
1784
+ const cache = /* @__PURE__ */ new Map();
1785
+ for (const item of items) {
1786
+ if (!isTextItem(item) || !item.str.trim()) continue;
1787
+ const t = item.transform ?? [];
1788
+ const fontSize = Math.hypot(t[2] ?? 0, t[3] ?? 0) || item.height || 10;
1789
+ let info;
1790
+ if (item.fontName && font) {
1791
+ if (!cache.has(item.fontName)) cache.set(item.fontName, font(item.fontName));
1792
+ info = cache.get(item.fontName);
1793
+ }
1794
+ runs.push({
1795
+ text: item.str,
1796
+ x: t[4] ?? 0,
1797
+ y: t[5] ?? 0,
1798
+ width: item.width,
1799
+ fontSize,
1800
+ fontName: info?.name ?? item.fontName,
1801
+ bold: info?.bold,
1802
+ italic: info?.italic
1803
+ });
1804
+ }
1805
+ return runs;
1806
+ }
1807
+ var DEFAULT_OPS = {
1808
+ save: 10,
1809
+ restore: 11,
1810
+ transform: 12,
1811
+ moveTo: 13,
1812
+ lineTo: 14,
1813
+ curveTo: 15,
1814
+ curveTo2: 16,
1815
+ curveTo3: 17,
1816
+ closePath: 18,
1817
+ rectangle: 19,
1818
+ stroke: 20,
1819
+ closeStroke: 21,
1820
+ fill: 22,
1821
+ eoFill: 23,
1822
+ fillStroke: 24,
1823
+ eoFillStroke: 25,
1824
+ closeFillStroke: 26,
1825
+ closeEOFillStroke: 27,
1826
+ endPath: 28,
1827
+ constructPath: 91
1828
+ };
1829
+ var DRAW_OPS = { moveTo: 0, lineTo: 1, curveTo: 2, quadraticCurveTo: 3, closePath: 4 };
1830
+ var MAX_PAGE_RULES = 5e3;
1831
+ var IDENTITY = [1, 0, 0, 1, 0, 0];
1832
+ var multiply = (m, c) => [
1833
+ m[0] * c[0] + m[1] * c[2],
1834
+ m[0] * c[1] + m[1] * c[3],
1835
+ m[2] * c[0] + m[3] * c[2],
1836
+ m[2] * c[1] + m[3] * c[3],
1837
+ m[4] * c[0] + m[5] * c[2] + c[4],
1838
+ m[4] * c[1] + m[5] * c[3] + c[5]
1839
+ ];
1840
+ var apply = (m, x, y) => [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
1841
+ function pdfOperatorListToRules(list, opsTable) {
1842
+ const OPS = { ...DEFAULT_OPS, ...opsTable ?? {} };
1843
+ const stroking = /* @__PURE__ */ new Set([OPS.stroke, OPS.closeStroke, OPS.fillStroke, OPS.eoFillStroke, OPS.closeFillStroke, OPS.closeEOFillStroke]);
1844
+ const filling = /* @__PURE__ */ new Set([OPS.fill, OPS.eoFill, OPS.fillStroke, OPS.eoFillStroke, OPS.closeFillStroke, OPS.closeEOFillStroke]);
1845
+ const rules = [];
1846
+ const stack = [];
1847
+ let ctm = IDENTITY;
1848
+ let lines = [];
1849
+ let rects = [];
1850
+ const num = (value) => typeof value === "number" && Number.isFinite(value) ? value : NaN;
1851
+ const addLine = (x1, y1, x2, y2) => {
1852
+ const [a, b] = apply(ctm, x1, y1);
1853
+ const [c, d] = apply(ctm, x2, y2);
1854
+ lines.push([a, b, c, d]);
1855
+ };
1856
+ const addRect = (x, y, w, h) => {
1857
+ const corners = [apply(ctm, x, y), apply(ctm, x + w, y), apply(ctm, x + w, y + h), apply(ctm, x, y + h)];
1858
+ const xs = corners.map((p) => p[0]);
1859
+ const ys = corners.map((p) => p[1]);
1860
+ rects.push([Math.min(...xs), Math.min(...ys), Math.max(...xs), Math.max(...ys)]);
1861
+ };
1862
+ const paint = (op) => {
1863
+ const stroke = stroking.has(op);
1864
+ const fill = filling.has(op);
1865
+ if (stroke) {
1866
+ for (const [x1, y1, x2, y2] of lines) rules.push({ x1, y1, x2, y2 });
1867
+ for (const [x0, y0, x1, y1] of rects) {
1868
+ rules.push({ x1: x0, y1: y0, x2: x1, y2: y0 }, { x1: x0, y1, x2: x1, y2: y1 });
1869
+ rules.push({ x1: x0, y1: y0, x2: x0, y2: y1 }, { x1, y1: y0, x2: x1, y2: y1 });
1870
+ }
1871
+ } else if (fill) {
1872
+ for (const [x0, y0, x1, y1] of rects) {
1873
+ if (y1 - y0 <= 2 && x1 - x0 > 2) rules.push({ x1: x0, y1: (y0 + y1) / 2, x2: x1, y2: (y0 + y1) / 2 });
1874
+ else if (x1 - x0 <= 2 && y1 - y0 > 2) rules.push({ x1: (x0 + x1) / 2, y1: y0, x2: (x0 + x1) / 2, y2: y1 });
1875
+ }
1876
+ }
1877
+ lines = [];
1878
+ rects = [];
1879
+ };
1880
+ const readPath = (subOps, subArgs) => {
1881
+ let k = 0;
1882
+ let cx = 0;
1883
+ let cy = 0;
1884
+ let sx = 0;
1885
+ let sy = 0;
1886
+ for (let i = 0; i < subOps.length; i++) {
1887
+ const op = subOps[i];
1888
+ if (op === OPS.moveTo) {
1889
+ cx = sx = num(subArgs[k++]);
1890
+ cy = sy = num(subArgs[k++]);
1891
+ } else if (op === OPS.lineTo) {
1892
+ const x = num(subArgs[k++]);
1893
+ const y = num(subArgs[k++]);
1894
+ addLine(cx, cy, x, y);
1895
+ cx = x;
1896
+ cy = y;
1897
+ } else if (op === OPS.rectangle) {
1898
+ addRect(num(subArgs[k++]), num(subArgs[k++]), num(subArgs[k++]), num(subArgs[k++]));
1899
+ } else if (op === OPS.curveTo) {
1900
+ k += 4;
1901
+ cx = num(subArgs[k++]);
1902
+ cy = num(subArgs[k++]);
1903
+ } else if (op === OPS.curveTo2 || op === OPS.curveTo3) {
1904
+ k += 2;
1905
+ cx = num(subArgs[k++]);
1906
+ cy = num(subArgs[k++]);
1907
+ } else if (op === OPS.closePath) {
1908
+ if (cx !== sx || cy !== sy) addLine(cx, cy, sx, sy);
1909
+ cx = sx;
1910
+ cy = sy;
1911
+ }
1912
+ }
1913
+ };
1914
+ const readDrawBuffer = (data) => {
1915
+ let cx = 0;
1916
+ let cy = 0;
1917
+ let sx = 0;
1918
+ let sy = 0;
1919
+ for (let k = 0; k < data.length; ) {
1920
+ const code = data[k++];
1921
+ if (code === DRAW_OPS.moveTo) {
1922
+ cx = sx = data[k++];
1923
+ cy = sy = data[k++];
1924
+ } else if (code === DRAW_OPS.lineTo) {
1925
+ const x = data[k++];
1926
+ const y = data[k++];
1927
+ addLine(cx, cy, x, y);
1928
+ cx = x;
1929
+ cy = y;
1930
+ } else if (code === DRAW_OPS.curveTo) {
1931
+ k += 4;
1932
+ cx = data[k++];
1933
+ cy = data[k++];
1934
+ } else if (code === DRAW_OPS.quadraticCurveTo) {
1935
+ k += 2;
1936
+ cx = data[k++];
1937
+ cy = data[k++];
1938
+ } else if (code === DRAW_OPS.closePath) {
1939
+ if (cx !== sx || cy !== sy) addLine(cx, cy, sx, sy);
1940
+ cx = sx;
1941
+ cy = sy;
1942
+ } else break;
1943
+ }
1944
+ };
1945
+ for (let i = 0; i < list.fnArray.length && rules.length < MAX_PAGE_RULES; i++) {
1946
+ const fn = list.fnArray[i];
1947
+ const args = list.argsArray[i];
1948
+ if (fn === OPS.save) stack.push(ctm);
1949
+ else if (fn === OPS.restore) ctm = stack.pop() ?? IDENTITY;
1950
+ else if (fn === OPS.transform && args && args.length >= 6) {
1951
+ const m = Array.from({ length: 6 }, (_, k) => num(args[k]));
1952
+ if (m.every(Number.isFinite)) ctm = multiply(m, ctm);
1953
+ } else if (fn === OPS.constructPath && args) {
1954
+ const first = args[0];
1955
+ if (typeof first === "number") {
1956
+ const buffers = args[1];
1957
+ const data = buffers?.[0];
1958
+ if (data && typeof data.length === "number") readDrawBuffer(data);
1959
+ paint(first);
1960
+ } else if (first && typeof first.length === "number") {
1961
+ readPath(first, args[1] ?? []);
1962
+ }
1963
+ } else if (stroking.has(fn) || filling.has(fn)) paint(fn);
1964
+ else if (fn === OPS.endPath) {
1965
+ lines = [];
1966
+ rects = [];
1967
+ }
1968
+ }
1969
+ return rules.filter((rule) => [rule.x1, rule.y1, rule.x2, rule.y2].every(Number.isFinite));
1970
+ }
1971
+ function fontResolver(page, content) {
1972
+ return (fontName) => {
1973
+ let info;
1974
+ try {
1975
+ if (page.commonObjs && (!page.commonObjs.has || page.commonObjs.has(fontName))) {
1976
+ const font = page.commonObjs.get(fontName);
1977
+ if (font && typeof font === "object") {
1978
+ info = {
1979
+ name: typeof font.name === "string" ? font.name : void 0,
1980
+ bold: font.bold || font.black ? true : void 0,
1981
+ italic: font.italic ? true : void 0
1982
+ };
1983
+ }
1984
+ }
1985
+ } catch {
1986
+ }
1987
+ const family = content.styles?.[fontName]?.fontFamily;
1988
+ if (!info?.name && family) info = { ...info, name: family };
1989
+ return info;
1990
+ };
1991
+ }
1992
+ function plainReport(paragraphs, pages) {
1993
+ return {
1994
+ mode: "plain",
1995
+ pages,
1996
+ counts: { headings: 0, lists: 0, tables: 0, paragraphs },
1997
+ multiColumnPages: 0,
1998
+ confidence: 1,
1999
+ items: [],
2000
+ removed: { headers: 0, footers: 0, pageNumbers: 0 },
2001
+ dehyphenated: 0
2002
+ };
2003
+ }
676
2004
  function createPdfImportAdapter(pdfjs, options = {}) {
677
2005
  return {
678
2006
  id: options.id ?? "pdf",
@@ -681,22 +2009,47 @@ function createPdfImportAdapter(pdfjs, options = {}) {
681
2009
  extensions: [".pdf"],
682
2010
  target: "document",
683
2011
  async import(_input, context) {
2012
+ const call = context.options && typeof context.options === "object" ? context.options : {};
2013
+ const opts = { ...options, ...call, layout: { ...options.layout, ...call.layout } };
2014
+ const structured = opts.structure !== false;
684
2015
  const data = new Uint8Array((await context.readArrayBuffer()).slice(0));
685
- const doc = await pdfjs.getDocument({ ...options.documentParams, data }).promise;
2016
+ const doc = await pdfjs.getDocument({ ...opts.documentParams, data }).promise;
686
2017
  const paragraphs = [];
2018
+ const layoutPages = [];
2019
+ let pages = 0;
687
2020
  try {
688
- const pages = Math.min(doc.numPages, options.maxPages ?? Infinity);
2021
+ pages = Math.min(doc.numPages, opts.maxPages ?? Infinity);
689
2022
  for (let n = 1; n <= pages; n++) {
690
2023
  const page = await doc.getPage(n);
691
- const content = await page.getTextContent();
692
- paragraphs.push(...pdfTextItemsToParagraphs(content.items, options));
2024
+ if (!structured) {
2025
+ const content = await page.getTextContent();
2026
+ paragraphs.push(...pdfTextItemsToParagraphs(content.items, opts));
2027
+ } else {
2028
+ let rules = [];
2029
+ if (opts.rulingLines !== false && typeof page.getOperatorList === "function") {
2030
+ try {
2031
+ rules = pdfOperatorListToRules(await page.getOperatorList(), pdfjs.OPS);
2032
+ } catch {
2033
+ rules = [];
2034
+ }
2035
+ }
2036
+ const content = await page.getTextContent();
2037
+ layoutPages.push({ runs: pdfTextItemsToRuns(content.items, fontResolver(page, content)), rules });
2038
+ }
693
2039
  page.cleanup?.();
694
2040
  }
695
2041
  } finally {
696
2042
  await doc.destroy?.();
697
2043
  }
698
- const text = paragraphs.join("\n");
699
- return { html: plainTextToParagraphHtml(text), text };
2044
+ if (!structured) {
2045
+ const text = paragraphs.join("\n");
2046
+ return { html: plainTextToParagraphHtml(text), text, structure: plainReport(paragraphs.length, pages) };
2047
+ }
2048
+ const layout = { ...opts.layout };
2049
+ if (layout.paragraphGap === void 0 && opts.paragraphGap !== void 0) layout.paragraphGap = opts.paragraphGap;
2050
+ const { blocks, report } = analyzePdfLayout(layoutPages, layout);
2051
+ const html = sanitizeImportedHtml(pdfLayoutBlocksToHtml(blocks));
2052
+ return { html, text: htmlToPlainText(html), structure: report };
700
2053
  }
701
2054
  };
702
2055
  }
@@ -795,15 +2148,29 @@ export {
795
2148
  BLOCK_CHANGE_ATTRIBUTE,
796
2149
  BUILT_IN_IMPORT_ADAPTERS,
797
2150
  Bookmark,
2151
+ CHARACTER_STYLE_MARK_NAME,
798
2152
  COMMENT_MARK_NAME,
2153
+ CONDITIONAL_FORMAT_ICON_SETS,
2154
+ CONDITIONAL_FORMAT_PRESETS,
2155
+ CONDITIONAL_FORMAT_STYLE_PRESETS,
2156
+ CONDITIONAL_FORMAT_TIME_PERIODS,
2157
+ CharacterStyle,
799
2158
  ColorHighlighter,
800
2159
  CommentStore,
801
2160
  Comments,
2161
+ ConditionalFormatEngine,
802
2162
  CrossReference,
2163
+ DATA_VALIDATION_ERROR_STYLE_OPTIONS,
2164
+ DATA_VALIDATION_OPERATOR_OPTIONS,
2165
+ DATA_VALIDATION_TYPE_OPTIONS,
803
2166
  DEFAULT_AUTOCORRECT_EXCEPTIONS,
804
2167
  DEFAULT_COLUMN_WIDTH,
2168
+ DEFAULT_CONDITIONAL_FORMAT_STYLE,
2169
+ DEFAULT_DATA_VALIDATION_MESSAGE,
2170
+ DEFAULT_DATA_VALIDATION_TITLE,
805
2171
  DEFAULT_DOCX_MAX_IMAGE_SIZE,
806
2172
  DEFAULT_ROW_HEIGHT,
2173
+ DEFAULT_STYLES,
807
2174
  DEFAULT_ZIP_MAX_ENTRIES,
808
2175
  DEFAULT_ZIP_MAX_TOTAL_SIZE,
809
2176
  DELETION_MARK_NAME,
@@ -812,6 +2179,7 @@ export {
812
2179
  DependencyGraph,
813
2180
  DirtyTracker,
814
2181
  DocumentCompare,
2182
+ EMPTY_CONDITIONAL_FORMAT_OVERLAY,
815
2183
  EMPTY_FIND_REPLACE_SNAPSHOT,
816
2184
  EditorController,
817
2185
  FIELD_ALIASES,
@@ -828,6 +2196,7 @@ export {
828
2196
  FootnoteReference,
829
2197
  Footnotes,
830
2198
  FormulaEvaluator,
2199
+ FormulaLambda,
831
2200
  FormulaParser,
832
2201
  GradientText,
833
2202
  HistoryManager,
@@ -840,26 +2209,36 @@ export {
840
2209
  MARKDOWN_MENTION_SPLIT_REGEX,
841
2210
  MAX_DATA_SOURCE_FIELDS,
842
2211
  MAX_DATA_SOURCE_RECORDS,
2212
+ MAX_DEFINED_NAME_LENGTH,
843
2213
  MAX_FIND_PATTERN_LENGTH,
844
2214
  MAX_FORMULA_ARRAY_SIZE,
2215
+ MAX_LAMBDA_DEPTH,
845
2216
  MAX_MERGE_LENGTH,
846
2217
  MAX_MERGE_OUTPUTS,
847
2218
  MAX_NUMBER_FORMAT_CODE_CHARS,
2219
+ MAX_SHEET_NAME_LENGTH,
848
2220
  MENTION_REGEX,
2221
+ MOVE_FROM_CLASS,
2222
+ MOVE_ID_ATTRIBUTE,
2223
+ MOVE_TO_CLASS,
849
2224
  Markdown,
850
2225
  Mention,
2226
+ NORMAL_STYLE_ID,
851
2227
  NUMBER_FORMAT_PRESETS,
852
2228
  NumberFormat,
853
2229
  Outline,
854
2230
  PIXERATE_DOCUMENT_MIME,
2231
+ ParagraphStyles,
855
2232
  RichClipboard,
856
2233
  SMILIE_REPLACEMENTS,
857
2234
  SPREADSHEET_CLIPBOARD_MIME,
858
2235
  SPREADSHEET_IMPORT_ADAPTERS,
859
2236
  SPREADSHEET_TABLE_ACTIONS,
2237
+ STYLE_ID_ATTRIBUTE,
860
2238
  SlashCommands,
861
2239
  SmilieReplacer,
862
2240
  SpreadsheetController,
2241
+ StyleRegistry,
863
2242
  TEMPLATE_DEPTH_ERROR,
864
2243
  TEMPLATE_LOOP_ERROR,
865
2244
  TEMPLATE_REGEX,
@@ -875,18 +2254,23 @@ export {
875
2254
  WHOLE_COLUMN_END_ROW,
876
2255
  ZipArchive,
877
2256
  ZipError,
2257
+ adjustRangeForStructuralChange,
2258
+ adjustRangesForStructuralChange,
878
2259
  aggregateValues,
2260
+ analyzePdfLayout,
879
2261
  applyDocumentComparison,
880
2262
  applyFormulaSuggestion,
881
2263
  applyReplacements,
882
2264
  autocorrectPluginKey,
883
2265
  bindDirtyToHistory,
884
2266
  bindSpreadsheetTableActions,
2267
+ blendConditionalFormatColors,
885
2268
  buildOutlineTree,
886
2269
  buildSpreadsheetView,
887
2270
  builtinNumberFormat,
888
2271
  builtinNumberFormatId,
889
2272
  capitalizeSentenceRules,
2273
+ captureSelectionFormat,
890
2274
  cellFormatForNumberFormat,
891
2275
  checkFormulaArgumentCount,
892
2276
  clampMenuPosition,
@@ -907,7 +2291,13 @@ export {
907
2291
  computeOutline,
908
2292
  computeRowGroups,
909
2293
  conditionSubject,
2294
+ conditionalFormatContrastColor,
2295
+ conditionalFormatIconCount,
2296
+ conditionalFormatNumber,
2297
+ conditionalFormatStyleString,
2298
+ copySheetName,
910
2299
  createCommentStore,
2300
+ createConditionalFormatRule,
911
2301
  createDirtyTracker,
912
2302
  createDocxImportAdapter,
913
2303
  createEditor,
@@ -918,20 +2308,26 @@ export {
918
2308
  createImportContext,
919
2309
  createMentionExtension,
920
2310
  createOutlineStore,
2311
+ createParagraphStylesStore,
921
2312
  createPdfImportAdapter,
922
2313
  createReviewId,
923
2314
  createRichTextPreset,
924
2315
  createSearchBudget,
925
2316
  createSpreadsheetClipboardData,
2317
+ createStyleRegistry,
926
2318
  createZipImportAdapter,
927
2319
  crossReferencePluginKey,
928
2320
  csvImportAdapter,
929
2321
  dateValueToSerial,
930
2322
  defaultAutocorrectRules,
2323
+ defaultIconThresholds,
931
2324
  defaultImportRegistry,
932
2325
  defaultIsEqual,
2326
+ deleteSheetInFormula,
933
2327
  describeBlockChange,
2328
+ describeConditionalFormat,
934
2329
  describeConditionalTag,
2330
+ describeDataValidation,
935
2331
  describeFormatChange,
936
2332
  describeFormulaError,
937
2333
  detectDelimiter,
@@ -945,12 +2341,14 @@ export {
945
2341
  escapeVariableText,
946
2342
  evaluateCondition,
947
2343
  evaluateConditionExpression,
2344
+ evaluateConditionalFormats,
948
2345
  evaluatePromptTokens,
949
2346
  expandReplacement,
950
2347
  extractCellDependencies,
951
2348
  extractInstructionNames,
952
2349
  extractMentions,
953
2350
  extractMentionsFromDoc,
2351
+ extractNameDependencies,
954
2352
  extractTemplateNames,
955
2353
  extractVariableNames,
956
2354
  extractVariables,
@@ -959,22 +2357,30 @@ export {
959
2357
  findAllMatches,
960
2358
  findAutocorrection,
961
2359
  findCommentRanges,
2360
+ findDataValidation,
962
2361
  findHexColors,
963
2362
  findImportAdapter,
2363
+ findInvalidCells,
964
2364
  findReplacePluginKey,
2365
+ findTextMentions,
965
2366
  foldCodePoint,
966
2367
  footnotesMarkdownIt,
967
2368
  footnotesPluginKey,
2369
+ forEachRangeCell,
968
2370
  formatCellDisplay,
969
2371
  formatCellForDisplay,
970
2372
  formatComparisonOperand,
971
2373
  formatConditionalTag,
972
2374
  formatFindStatus,
973
2375
  formatGeneralFit,
2376
+ formatMentionText,
974
2377
  formatNumberFormatValue,
975
2378
  formatReviewTime,
2379
+ formatRuleRanges,
2380
+ formatSheetPrefix,
976
2381
  formatTextFunction,
977
2382
  formatValueWithCode,
2383
+ formulaIdentifiers,
978
2384
  fractionRules,
979
2385
  getActiveHeading,
980
2386
  getBookmarks,
@@ -983,7 +2389,10 @@ export {
983
2389
  getCommentAuthor,
984
2390
  getCommentIdsAt,
985
2391
  getCommentStore,
2392
+ getConditionalFormatCss,
2393
+ getConditionalFormatIcon,
986
2394
  getCrossReferenceTargets,
2395
+ getDataBarCss,
987
2396
  getDocumentStructureCommandItems,
988
2397
  getEditorMarkdown,
989
2398
  getEditorText,
@@ -999,11 +2408,16 @@ export {
999
2408
  getFormulaSignatureParts,
1000
2409
  getImportAccept,
1001
2410
  getLatestVersion,
2411
+ getMentionNodes,
2412
+ getNameManagerRows,
1002
2413
  getOutline,
2414
+ getParagraphStyleAt,
1003
2415
  getPromptDiagnostics,
1004
2416
  getRowSection,
1005
2417
  getSchemaSignature,
2418
+ getSheetTabMenuItems,
1006
2419
  getSpreadsheetMenuItems,
2420
+ getStyleRegistry,
1007
2421
  getSuppliedValue,
1008
2422
  getTableOfContentsEntries,
1009
2423
  getTableSections,
@@ -1011,6 +2425,7 @@ export {
1011
2425
  getTrackChangesStore,
1012
2426
  getTrackedChangeAt,
1013
2427
  getTrackedChanges,
2428
+ getValidationListValues,
1014
2429
  getVariableFormFields,
1015
2430
  handleImageInsertion,
1016
2431
  htmlImportAdapter,
@@ -1026,12 +2441,17 @@ export {
1026
2441
  instructionRegex,
1027
2442
  isBlankValue,
1028
2443
  isFormulaError,
2444
+ isFormulaLambda,
1029
2445
  isGeneralNumberFormat,
1030
2446
  isInsidePromptToken,
2447
+ isLambdaDefinition,
2448
+ isMoveSized,
2449
+ isParagraphStyleAvailable,
1031
2450
  isPromptValueSet,
1032
2451
  isSingleCellRange,
1033
2452
  isTrackChangesEnabled,
1034
2453
  isUnsafeZipPath,
2454
+ isValidStyleId,
1035
2455
  listFormulaFunctions,
1036
2456
  mapFormulaReferences,
1037
2457
  mapRawOffsetToResolved,
@@ -1041,8 +2461,10 @@ export {
1041
2461
  matchConditionalTags,
1042
2462
  matchFields,
1043
2463
  matchesFilterRule,
2464
+ matchesTimePeriod,
1044
2465
  mergeRecords,
1045
2466
  navigateToHeading,
2467
+ nextSheetName,
1046
2468
  normalizeFieldKey,
1047
2469
  normalizeFieldNames,
1048
2470
  normalizeRange,
@@ -1051,6 +2473,7 @@ export {
1051
2473
  numberToText,
1052
2474
  offsetFormulaReferences,
1053
2475
  outlinePluginKey,
2476
+ paragraphStylesPluginKey,
1054
2477
  parseCellInput,
1055
2478
  parseCellReference,
1056
2479
  parseComparison,
@@ -1065,9 +2488,13 @@ export {
1065
2488
  parseRange,
1066
2489
  parseReplacement,
1067
2490
  parseRichClipboardPayload,
2491
+ parseRuleRanges,
1068
2492
  parseTsv,
1069
2493
  parseVariableBody,
2494
+ pdfLayoutBlocksToHtml,
2495
+ pdfOperatorListToRules,
1070
2496
  pdfTextItemsToParagraphs,
2497
+ pdfTextItemsToRuns,
1071
2498
  pickImportFiles,
1072
2499
  plainTextImportAdapter,
1073
2500
  plainTextToParagraphHtml,
@@ -1075,8 +2502,10 @@ export {
1075
2502
  plainTextToTipTapHtml,
1076
2503
  preprocessMarkdownFileLinks,
1077
2504
  preprocessMarkdownMentions,
2505
+ quoteSheetName,
1078
2506
  rangeContains,
1079
2507
  rangeContainsRange,
2508
+ rangesContain,
1080
2509
  rangesIntersect,
1081
2510
  readRichClipboard,
1082
2511
  readSpreadsheetClipboard,
@@ -1088,6 +2517,8 @@ export {
1088
2517
  registerSpreadsheetImportAdapters,
1089
2518
  remapFormulaReferences,
1090
2519
  removeImageNode,
2520
+ renameNameInFormula,
2521
+ renameSheetInFormula,
1091
2522
  resolvePrompt,
1092
2523
  resolveTemplates,
1093
2524
  resolveTemplatesWithMapping,
@@ -1098,7 +2529,10 @@ export {
1098
2529
  rowPassesFilters,
1099
2530
  rtfImportAdapter,
1100
2531
  rtfToPlainText,
2532
+ ruleAnchor,
2533
+ ruleFormulaAt,
1101
2534
  runSpreadsheetMenuItem,
2535
+ safeCSSValue,
1102
2536
  sanitizeHtml,
1103
2537
  sanitizeImportedHtml,
1104
2538
  searchDocument,
@@ -1109,12 +2543,20 @@ export {
1109
2543
  serializeMergeOutputs,
1110
2544
  serializeRichClipboardPayload,
1111
2545
  serializeTsv,
2546
+ setMentionRoleAt,
2547
+ setMentionRoleInText,
2548
+ sheetDropIndex,
2549
+ sheetNameNeedsQuotes,
1112
2550
  shiftFormulaReferences,
2551
+ shiftRuleFormula,
1113
2552
  smartQuoteRules,
1114
2553
  smilieAutocorrectRules,
1115
2554
  sortCompareValues,
1116
2555
  sortZipEntryNames,
1117
2556
  stripMarkdownCode,
2557
+ subtractRange,
2558
+ subtractRangeFromRanges,
2559
+ summarizeImportStructure,
1118
2560
  symbolRules,
1119
2561
  syncFootnotes,
1120
2562
  tableOfContentsMarkdownIt,
@@ -1125,13 +2567,17 @@ export {
1125
2567
  tokenizePrompt,
1126
2568
  tokenizePromptWithDiagnostics,
1127
2569
  trackChangesPluginKey,
2570
+ trackedChangeLabel,
1128
2571
  tsvImportAdapter,
1129
2572
  twoInitialCapitalsRules,
1130
2573
  unescapeVariableText,
1131
2574
  unregisterFormulaFunction,
1132
2575
  unregisterImportAdapter,
1133
2576
  updateImageSrc,
2577
+ validateCellInput,
2578
+ validateDefinedName,
1134
2579
  validateFindPattern,
2580
+ validateSheetName,
1135
2581
  variableRegex,
1136
2582
  wildcardToRegExp,
1137
2583
  withoutDirty,