@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.
- package/README.md +71 -1
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/dist/agent/index.cjs +10 -9
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +1 -1
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +4 -3
- package/dist/agent/index.js.map +1 -1
- package/dist/canvas/index.cjs +3173 -340
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +617 -4
- package/dist/canvas/index.d.ts +617 -4
- package/dist/canvas/index.js +3105 -272
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-4BVP64JJ.cjs +1406 -0
- package/dist/chunk-4BVP64JJ.cjs.map +1 -0
- package/dist/{chunk-XNORY7M6.cjs → chunk-7WISYZFO.cjs} +105 -50
- package/dist/chunk-7WISYZFO.cjs.map +1 -0
- package/dist/{chunk-OLZJXL4R.cjs → chunk-AL6JMGWW.cjs} +59 -25
- package/dist/chunk-AL6JMGWW.cjs.map +1 -0
- package/dist/chunk-BVP3TSLH.cjs +69 -0
- package/dist/chunk-BVP3TSLH.cjs.map +1 -0
- package/dist/{chunk-MCSJFWAO.cjs → chunk-C7P22VIP.cjs} +670 -96
- package/dist/chunk-C7P22VIP.cjs.map +1 -0
- package/dist/{chunk-PGNZKFQS.js → chunk-ECCCYKGL.js} +76 -21
- package/dist/chunk-ECCCYKGL.js.map +1 -0
- package/dist/{chunk-3CN2WD3X.js → chunk-FH6F67DN.js} +646 -72
- package/dist/chunk-FH6F67DN.js.map +1 -0
- package/dist/chunk-HRMEDT2L.js +1406 -0
- package/dist/chunk-HRMEDT2L.js.map +1 -0
- package/dist/{chunk-ITBSKI26.js → chunk-IXHSYOVY.js} +941 -9
- package/dist/chunk-IXHSYOVY.js.map +1 -0
- package/dist/{chunk-FODNLX5N.js → chunk-NAXVVS5I.js} +38 -4
- package/dist/chunk-NAXVVS5I.js.map +1 -0
- package/dist/chunk-O5RYH2PG.js +69 -0
- package/dist/chunk-O5RYH2PG.js.map +1 -0
- package/dist/{chunk-SBCZ6RN5.cjs → chunk-PO6A6QQH.cjs} +1039 -107
- package/dist/chunk-PO6A6QQH.cjs.map +1 -0
- package/dist/{chunk-3LV6RRPH.js → chunk-QGYDWPRM.js} +2 -2
- package/dist/{chunk-U5KWZU4X.js → chunk-RR7F5GUM.js} +2632 -129
- package/dist/chunk-RR7F5GUM.js.map +1 -0
- package/dist/{chunk-5S3Z4PPF.js → chunk-UAKDG62Z.js} +232 -25
- package/dist/chunk-UAKDG62Z.js.map +1 -0
- package/dist/{chunk-SML64VJG.cjs → chunk-V3CHHWOE.cjs} +4 -4
- package/dist/{chunk-SML64VJG.cjs.map → chunk-V3CHHWOE.cjs.map} +1 -1
- package/dist/chunk-WSQKHXW7.cjs +5726 -0
- package/dist/chunk-WSQKHXW7.cjs.map +1 -0
- package/dist/{chunk-D27YFC46.cjs → chunk-X4N4WUKB.cjs} +267 -60
- package/dist/chunk-X4N4WUKB.cjs.map +1 -0
- package/dist/commands/index.cjs +74 -1
- package/dist/commands/index.cjs.map +1 -1
- package/dist/commands/index.d.cts +34 -1
- package/dist/commands/index.d.ts +34 -1
- package/dist/commands/index.js +73 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/compare/index.cjs +3 -3
- package/dist/compare/index.d.cts +1 -1
- package/dist/compare/index.d.ts +1 -1
- package/dist/compare/index.js +2 -2
- package/dist/controller-BIJiNoVs.d.cts +1842 -0
- package/dist/controller-BIJiNoVs.d.ts +1842 -0
- package/dist/{documents-BQjzJNe2.d.ts → documents-CHT1U5Vs.d.ts} +10 -0
- package/dist/{documents-KRTPhvst.d.cts → documents-Gp7wb0Me.d.cts} +10 -0
- package/dist/extensions/index.cjs +53 -6
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +12 -4
- package/dist/extensions/index.d.ts +12 -4
- package/dist/extensions/index.js +53 -6
- package/dist/generation/index.cjs +1013 -69
- package/dist/generation/index.cjs.map +1 -1
- package/dist/generation/index.d.cts +474 -13
- package/dist/generation/index.d.ts +474 -13
- package/dist/generation/index.js +976 -32
- package/dist/generation/index.js.map +1 -1
- package/dist/image-editor/index.cjs +3385 -1275
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +693 -128
- package/dist/image-editor/index.d.ts +693 -128
- package/dist/image-editor/index.js +3325 -1215
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{index-fJrlkJCd.d.ts → index-7a6bHTLy.d.ts} +494 -5
- package/dist/{index-BhJBSm2d.d.cts → index-Csd5qI8u.d.cts} +494 -5
- package/dist/index.cjs +1491 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -19
- package/dist/index.d.ts +110 -19
- package/dist/index.js +1464 -18
- package/dist/index.js.map +1 -1
- package/dist/mention-text-CDnCFd3c.d.cts +53 -0
- package/dist/mention-text-CDnCFd3c.d.ts +53 -0
- package/dist/model-C1zApQM8.d.cts +219 -0
- package/dist/model-C1zApQM8.d.ts +219 -0
- package/dist/persistence/index.d.cts +3 -120
- package/dist/persistence/index.d.ts +3 -120
- package/dist/{registry-GJI4gToU.d.cts → registry-CEgwXED1.d.cts} +12 -1
- package/dist/{registry-GJI4gToU.d.ts → registry-CEgwXED1.d.ts} +12 -1
- package/dist/serializers/index.cjs +12 -4
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +39 -12
- package/dist/serializers/index.d.ts +39 -12
- package/dist/serializers/index.js +12 -4
- package/dist/spreadsheet/index.cjs +127 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +431 -11
- package/dist/spreadsheet/index.d.ts +431 -11
- package/dist/spreadsheet/index.js +127 -3
- package/dist/storage-BpFfspHm.d.cts +120 -0
- package/dist/storage-BpFfspHm.d.ts +120 -0
- package/dist/tokens/index.cjs +115 -0
- package/dist/tokens/index.cjs.map +1 -0
- package/dist/tokens/index.d.cts +212 -0
- package/dist/tokens/index.d.ts +212 -0
- package/dist/tokens/index.js +115 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/{track-changes-BK5sVf4_.d.cts → track-changes-D_VAPELi.d.cts} +95 -11
- package/dist/{track-changes-CDjCrwKe.d.ts → track-changes-Db_fGEvx.d.ts} +95 -11
- package/package.json +6 -1
- package/dist/chunk-3CN2WD3X.js.map +0 -1
- package/dist/chunk-5S3Z4PPF.js.map +0 -1
- package/dist/chunk-D27YFC46.cjs.map +0 -1
- package/dist/chunk-FODNLX5N.js.map +0 -1
- package/dist/chunk-ITBSKI26.js.map +0 -1
- package/dist/chunk-MA2F5KHF.cjs +0 -3223
- package/dist/chunk-MA2F5KHF.cjs.map +0 -1
- package/dist/chunk-MCSJFWAO.cjs.map +0 -1
- package/dist/chunk-OLZJXL4R.cjs.map +0 -1
- package/dist/chunk-PGNZKFQS.js.map +0 -1
- package/dist/chunk-SBCZ6RN5.cjs.map +0 -1
- package/dist/chunk-U5KWZU4X.js.map +0 -1
- package/dist/chunk-XNORY7M6.cjs.map +0 -1
- package/dist/controller-BhLLAoi8.d.cts +0 -1000
- package/dist/controller-BhLLAoi8.d.ts +0 -1000
- /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-
|
|
181
|
+
} from "./chunk-IXHSYOVY.js";
|
|
164
182
|
import {
|
|
165
183
|
compareDocuments,
|
|
166
184
|
compareHtml,
|
|
167
185
|
diffChanges,
|
|
168
186
|
diffSequences
|
|
169
|
-
} from "./chunk-
|
|
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-
|
|
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
|
-
|
|
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-
|
|
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
|
-
|
|
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-
|
|
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
|
|
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 =
|
|
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({ ...
|
|
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
|
-
|
|
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
|
-
|
|
692
|
-
|
|
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
|
-
|
|
699
|
-
|
|
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,
|