@pixerate/editor 0.24.0 → 0.26.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 +101 -1
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/agent/index.cjs +175 -11
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +18 -4
- package/dist/agent/index.d.ts +18 -4
- package/dist/agent/index.js +168 -4
- package/dist/agent/index.js.map +1 -1
- package/dist/{arrangeShortcuts-B8O3f8-P.d.cts → arrange-BICutYPk.d.cts} +243 -29
- package/dist/{arrangeShortcuts-sLlD2rSX.d.ts → arrange-BICutYPk.d.ts} +243 -29
- package/dist/builtins-CdPcLwwF.d.cts +176 -0
- package/dist/builtins-Chj6zv_O.d.ts +176 -0
- package/dist/canvas/index.cjs +8588 -1857
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +1847 -9
- package/dist/canvas/index.d.ts +1847 -9
- package/dist/canvas/index.js +8577 -1846
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-3CC7OPUQ.cjs +831 -0
- package/dist/chunk-3CC7OPUQ.cjs.map +1 -0
- package/dist/chunk-4BVP64JJ.cjs +1406 -0
- package/dist/chunk-4BVP64JJ.cjs.map +1 -0
- package/dist/chunk-BVP3TSLH.cjs +69 -0
- package/dist/chunk-BVP3TSLH.cjs.map +1 -0
- package/dist/{chunk-OLZJXL4R.cjs → chunk-CS6NZWWA.cjs} +59 -25
- package/dist/chunk-CS6NZWWA.cjs.map +1 -0
- package/dist/{chunk-MCSJFWAO.cjs → chunk-EWCOFSCQ.cjs} +685 -100
- package/dist/chunk-EWCOFSCQ.cjs.map +1 -0
- package/dist/chunk-HDYMLS3X.cjs +409 -0
- package/dist/chunk-HDYMLS3X.cjs.map +1 -0
- package/dist/chunk-HRMEDT2L.js +1406 -0
- package/dist/chunk-HRMEDT2L.js.map +1 -0
- package/dist/{chunk-D27YFC46.cjs → chunk-IFHKKVXH.cjs} +382 -63
- package/dist/chunk-IFHKKVXH.cjs.map +1 -0
- package/dist/{chunk-PGNZKFQS.js → chunk-JOIREKL7.js} +137 -58
- package/dist/chunk-JOIREKL7.js.map +1 -0
- package/dist/chunk-KRGXUQ2Y.js +1696 -0
- package/dist/chunk-KRGXUQ2Y.js.map +1 -0
- package/dist/{chunk-3LV6RRPH.js → chunk-MHEPLBFB.js} +2 -2
- package/dist/chunk-MR2764X2.js +831 -0
- package/dist/chunk-MR2764X2.js.map +1 -0
- package/dist/{chunk-XNORY7M6.cjs → chunk-NFVBT3UZ.cjs} +166 -87
- package/dist/chunk-NFVBT3UZ.cjs.map +1 -0
- package/dist/chunk-NQF32I6Z.cjs +6478 -0
- package/dist/chunk-NQF32I6Z.cjs.map +1 -0
- package/dist/chunk-O5RYH2PG.js +69 -0
- package/dist/chunk-O5RYH2PG.js.map +1 -0
- package/dist/{chunk-ITBSKI26.js → chunk-Q2OHWD2A.js} +1064 -360
- package/dist/chunk-Q2OHWD2A.js.map +1 -0
- package/dist/{chunk-FODNLX5N.js → chunk-QJSOZFCZ.js} +38 -4
- package/dist/chunk-QJSOZFCZ.js.map +1 -0
- package/dist/{chunk-SML64VJG.cjs → chunk-RRREAOVM.cjs} +4 -4
- package/dist/{chunk-SML64VJG.cjs.map → chunk-RRREAOVM.cjs.map} +1 -1
- package/dist/{chunk-5S3Z4PPF.js → chunk-SWE3NPOU.js} +347 -28
- package/dist/chunk-SWE3NPOU.js.map +1 -0
- package/dist/chunk-TXXNBDQX.cjs +1696 -0
- package/dist/chunk-TXXNBDQX.cjs.map +1 -0
- package/dist/chunk-UBCFIABU.js +409 -0
- package/dist/chunk-UBCFIABU.js.map +1 -0
- package/dist/chunk-X7HXL2SB.js +6478 -0
- package/dist/chunk-X7HXL2SB.js.map +1 -0
- package/dist/{chunk-SBCZ6RN5.cjs → chunk-YOMYSFJU.cjs} +1163 -459
- package/dist/chunk-YOMYSFJU.cjs.map +1 -0
- package/dist/{chunk-3CN2WD3X.js → chunk-ZRNHGAQT.js} +661 -76
- package/dist/chunk-ZRNHGAQT.js.map +1 -0
- package/dist/commands/index.cjs +425 -4
- package/dist/commands/index.cjs.map +1 -1
- package/dist/commands/index.d.cts +39 -77
- package/dist/commands/index.d.ts +39 -77
- package/dist/commands/index.js +424 -3
- 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-CxXGOEmy.d.cts +2038 -0
- package/dist/controller-CxXGOEmy.d.ts +2038 -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/export/index.cjs +36 -0
- package/dist/export/index.cjs.map +1 -0
- package/dist/export/index.d.cts +243 -0
- package/dist/export/index.d.ts +243 -0
- package/dist/export/index.js +36 -0
- package/dist/export/index.js.map +1 -0
- package/dist/extensions/index.cjs +101 -6
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +18 -5
- package/dist/extensions/index.d.ts +18 -5
- package/dist/extensions/index.js +101 -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-B273Zllk.d.ts} +500 -7
- package/dist/{index-BhJBSm2d.d.cts → index-jcJwmBYt.d.cts} +500 -7
- package/dist/index.cjs +1603 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +154 -27
- package/dist/index.d.ts +154 -27
- package/dist/index.js +1584 -26
- 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-CED5C0lA.d.cts +204 -0
- package/dist/registry-CED5C0lA.d.ts +204 -0
- 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/{registry-D32LpIc4.d.cts → registry-D0GADKc7.d.cts} +1 -1
- package/dist/{registry-evKTP4ls.d.ts → registry-DhVUZioj.d.ts} +1 -1
- package/dist/serializers/index.cjs +12 -4
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +41 -13
- package/dist/serializers/index.d.ts +41 -13
- package/dist/serializers/index.js +12 -4
- package/dist/spreadsheet/index.cjs +157 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +534 -11
- package/dist/spreadsheet/index.d.ts +534 -11
- package/dist/spreadsheet/index.js +157 -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 +15 -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 +0 -3223
- 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/types-DX4Mh4SL.d.cts +0 -217
- package/dist/types-DX4Mh4SL.d.ts +0 -217
- /package/dist/{chunk-3LV6RRPH.js.map → chunk-MHEPLBFB.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import "./chunk-HLIMTC6N.js";
|
|
2
|
+
import {
|
|
3
|
+
DOCX_ANONYMOUS_AUTHOR,
|
|
4
|
+
DOCX_EXPORT_MIME_TYPE,
|
|
5
|
+
DocxExportController,
|
|
6
|
+
XmlWriter,
|
|
7
|
+
createDocxExportController,
|
|
8
|
+
createDocxParts,
|
|
9
|
+
deflateRaw,
|
|
10
|
+
docxFileName,
|
|
11
|
+
downloadBlob,
|
|
12
|
+
escapeXmlAttr,
|
|
13
|
+
escapeXmlText,
|
|
14
|
+
exportDocx,
|
|
15
|
+
exportDocxBlob,
|
|
16
|
+
stripInvalidXmlChars,
|
|
17
|
+
writeZip
|
|
18
|
+
} from "./chunk-KRGXUQ2Y.js";
|
|
2
19
|
import {
|
|
3
20
|
FIELD_ALIASES,
|
|
4
21
|
MAX_DATA_SOURCE_FIELDS,
|
|
@@ -40,14 +57,14 @@ import {
|
|
|
40
57
|
Autocorrect,
|
|
41
58
|
BUILT_IN_IMPORT_ADAPTERS,
|
|
42
59
|
Bookmark,
|
|
60
|
+
CHARACTER_STYLE_MARK_NAME,
|
|
43
61
|
COMMENT_MARK_NAME,
|
|
62
|
+
CharacterStyle,
|
|
44
63
|
ColorHighlighter,
|
|
45
64
|
Comments,
|
|
46
65
|
CrossReference,
|
|
47
66
|
DEFAULT_AUTOCORRECT_EXCEPTIONS,
|
|
48
67
|
DEFAULT_DOCX_MAX_IMAGE_SIZE,
|
|
49
|
-
DEFAULT_ZIP_MAX_ENTRIES,
|
|
50
|
-
DEFAULT_ZIP_MAX_TOTAL_SIZE,
|
|
51
68
|
DOCX_MIME_TYPES,
|
|
52
69
|
DocumentCompare,
|
|
53
70
|
EMPTY_FIND_REPLACE_SNAPSHOT,
|
|
@@ -69,19 +86,21 @@ import {
|
|
|
69
86
|
Markdown,
|
|
70
87
|
Mention,
|
|
71
88
|
Outline,
|
|
89
|
+
ParagraphStyles,
|
|
72
90
|
RichClipboard,
|
|
73
91
|
SMILIE_REPLACEMENTS,
|
|
92
|
+
STYLE_ID_ATTRIBUTE,
|
|
74
93
|
SlashCommands,
|
|
75
94
|
SmilieReplacer,
|
|
76
95
|
TableOfContents,
|
|
77
96
|
TemplateSuggestions,
|
|
78
|
-
ZipArchive,
|
|
79
|
-
ZipError,
|
|
80
97
|
applyDocumentComparison,
|
|
98
|
+
applyImportedReviewData,
|
|
81
99
|
applyReplacements,
|
|
82
100
|
autocorrectPluginKey,
|
|
83
101
|
buildOutlineTree,
|
|
84
102
|
capitalizeSentenceRules,
|
|
103
|
+
captureSelectionFormat,
|
|
85
104
|
commentsPluginKey,
|
|
86
105
|
compareInEditor,
|
|
87
106
|
compileFindPattern,
|
|
@@ -92,8 +111,10 @@ import {
|
|
|
92
111
|
createImportContext,
|
|
93
112
|
createMentionExtension,
|
|
94
113
|
createOutlineStore,
|
|
114
|
+
createParagraphStylesStore,
|
|
95
115
|
createRichTextPreset,
|
|
96
116
|
createSearchBudget,
|
|
117
|
+
createTableCommands,
|
|
97
118
|
crossReferencePluginKey,
|
|
98
119
|
defaultAutocorrectRules,
|
|
99
120
|
defaultImportRegistry,
|
|
@@ -125,7 +146,10 @@ import {
|
|
|
125
146
|
getFindReplaceStore,
|
|
126
147
|
getFootnotes,
|
|
127
148
|
getImportAccept,
|
|
149
|
+
getMentionNodes,
|
|
128
150
|
getOutline,
|
|
151
|
+
getParagraphStyleAt,
|
|
152
|
+
getStyleRegistry,
|
|
129
153
|
getTableOfContentsEntries,
|
|
130
154
|
handleImageInsertion,
|
|
131
155
|
htmlImportAdapter,
|
|
@@ -136,18 +160,19 @@ import {
|
|
|
136
160
|
insertImageNode,
|
|
137
161
|
insertImportedDocument,
|
|
138
162
|
isInsidePromptToken,
|
|
139
|
-
|
|
163
|
+
isParagraphStyleAvailable,
|
|
140
164
|
markdownImportAdapter,
|
|
141
165
|
navigateToHeading,
|
|
142
166
|
outlinePluginKey,
|
|
167
|
+
paragraphStylesPluginKey,
|
|
143
168
|
parseReplacement,
|
|
144
169
|
plainTextImportAdapter,
|
|
145
|
-
readZip,
|
|
146
170
|
registerImportAdapter,
|
|
147
171
|
removeImageNode,
|
|
148
172
|
richClipboardPluginKey,
|
|
149
173
|
rtfImportAdapter,
|
|
150
174
|
searchDocument,
|
|
175
|
+
setMentionRoleAt,
|
|
151
176
|
smartQuoteRules,
|
|
152
177
|
smilieAutocorrectRules,
|
|
153
178
|
symbolRules,
|
|
@@ -158,15 +183,29 @@ import {
|
|
|
158
183
|
unregisterImportAdapter,
|
|
159
184
|
updateImageSrc,
|
|
160
185
|
validateFindPattern,
|
|
161
|
-
writeRichClipboard
|
|
162
|
-
|
|
163
|
-
} from "./chunk-ITBSKI26.js";
|
|
186
|
+
writeRichClipboard
|
|
187
|
+
} from "./chunk-Q2OHWD2A.js";
|
|
164
188
|
import {
|
|
165
189
|
compareDocuments,
|
|
166
190
|
compareHtml,
|
|
167
191
|
diffChanges,
|
|
168
192
|
diffSequences
|
|
169
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-QJSOZFCZ.js";
|
|
194
|
+
import {
|
|
195
|
+
DEFAULT_STYLES,
|
|
196
|
+
DEFAULT_ZIP_MAX_ENTRIES,
|
|
197
|
+
DEFAULT_ZIP_MAX_TOTAL_SIZE,
|
|
198
|
+
NORMAL_STYLE_ID,
|
|
199
|
+
StyleRegistry,
|
|
200
|
+
ZipArchive,
|
|
201
|
+
ZipError,
|
|
202
|
+
createStyleRegistry,
|
|
203
|
+
isUnsafeZipPath,
|
|
204
|
+
isValidStyleId,
|
|
205
|
+
readZip,
|
|
206
|
+
safeCSSValue,
|
|
207
|
+
zipCrc32
|
|
208
|
+
} from "./chunk-MR2764X2.js";
|
|
170
209
|
import {
|
|
171
210
|
INSTRUCTION_REGEX,
|
|
172
211
|
TEMPLATE_REGEX,
|
|
@@ -201,20 +240,44 @@ import {
|
|
|
201
240
|
rtfToPlainText,
|
|
202
241
|
sanitizeImportedHtml,
|
|
203
242
|
serializeRichClipboardPayload
|
|
204
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-MHEPLBFB.js";
|
|
205
244
|
import {
|
|
245
|
+
CONDITIONAL_FORMAT_ICON_SETS,
|
|
246
|
+
CONDITIONAL_FORMAT_PRESETS,
|
|
247
|
+
CONDITIONAL_FORMAT_STYLE_PRESETS,
|
|
248
|
+
CONDITIONAL_FORMAT_TIME_PERIODS,
|
|
249
|
+
ConditionalFormatEngine,
|
|
250
|
+
DATA_VALIDATION_ERROR_STYLE_OPTIONS,
|
|
251
|
+
DATA_VALIDATION_OPERATOR_OPTIONS,
|
|
252
|
+
DATA_VALIDATION_TYPE_OPTIONS,
|
|
206
253
|
DEFAULT_COLUMN_WIDTH,
|
|
254
|
+
DEFAULT_CONDITIONAL_FORMAT_STYLE,
|
|
255
|
+
DEFAULT_DATA_VALIDATION_MESSAGE,
|
|
256
|
+
DEFAULT_DATA_VALIDATION_TITLE,
|
|
207
257
|
DEFAULT_ROW_HEIGHT,
|
|
208
258
|
DataSourceBinder,
|
|
209
259
|
DependencyGraph,
|
|
260
|
+
EMPTY_CONDITIONAL_FORMAT_OVERLAY,
|
|
261
|
+
IntervalIndex,
|
|
262
|
+
MAX_DEFINED_NAME_LENGTH,
|
|
263
|
+
MAX_SHEET_NAME_LENGTH,
|
|
210
264
|
NUMBER_FORMAT_PRESETS,
|
|
211
265
|
SPREADSHEET_CLIPBOARD_MIME,
|
|
266
|
+
SPREADSHEET_COLUMN_HEADER_HEIGHT,
|
|
267
|
+
SPREADSHEET_DEFAULT_VIEWPORT,
|
|
268
|
+
SPREADSHEET_GROUP_ROW_HEIGHT,
|
|
212
269
|
SPREADSHEET_IMPORT_ADAPTERS,
|
|
270
|
+
SPREADSHEET_ROW_HEADER_WIDTH,
|
|
213
271
|
SPREADSHEET_TABLE_ACTIONS,
|
|
272
|
+
SPREADSHEET_VIRTUAL_COLUMN_THRESHOLD,
|
|
273
|
+
SPREADSHEET_VIRTUAL_ROW_THRESHOLD,
|
|
214
274
|
SpreadsheetController,
|
|
275
|
+
adjustRangeForStructuralChange,
|
|
276
|
+
adjustRangesForStructuralChange,
|
|
215
277
|
aggregateValues,
|
|
216
278
|
applyFormulaSuggestion,
|
|
217
279
|
bindSpreadsheetTableActions,
|
|
280
|
+
blendConditionalFormatColors,
|
|
218
281
|
buildSpreadsheetView,
|
|
219
282
|
cellFormatForNumberFormat,
|
|
220
283
|
clampMenuPosition,
|
|
@@ -222,44 +285,94 @@ import {
|
|
|
222
285
|
compareCellValues,
|
|
223
286
|
computeFillTarget,
|
|
224
287
|
computeRowGroups,
|
|
288
|
+
conditionalFormatContrastColor,
|
|
289
|
+
conditionalFormatIconCount,
|
|
290
|
+
conditionalFormatNumber,
|
|
291
|
+
conditionalFormatStyleString,
|
|
292
|
+
copySheetName,
|
|
293
|
+
createConditionalFormatRule,
|
|
225
294
|
createSpreadsheetClipboardData,
|
|
226
295
|
csvImportAdapter,
|
|
296
|
+
defaultIconThresholds,
|
|
297
|
+
deleteSheetInFormula,
|
|
298
|
+
describeConditionalFormat,
|
|
299
|
+
describeDataValidation,
|
|
300
|
+
evaluateConditionalFormats,
|
|
227
301
|
extractCellDependencies,
|
|
302
|
+
extractNameDependencies,
|
|
303
|
+
extractReferenceDependencies,
|
|
228
304
|
fillSeries,
|
|
305
|
+
findDataValidation,
|
|
306
|
+
findInvalidCells,
|
|
307
|
+
forEachRangeCell,
|
|
229
308
|
formatCellDisplay,
|
|
230
309
|
formatCellForDisplay,
|
|
310
|
+
formatRuleRanges,
|
|
311
|
+
formatSheetPrefix,
|
|
231
312
|
formatValueWithCode,
|
|
313
|
+
formulaIdentifiers,
|
|
314
|
+
fullSpreadsheetViewWindow,
|
|
315
|
+
getConditionalFormatCss,
|
|
316
|
+
getConditionalFormatIcon,
|
|
317
|
+
getDataBarCss,
|
|
232
318
|
getFillDirection,
|
|
233
319
|
getFormulaCaretContext,
|
|
234
320
|
getFormulaHints,
|
|
321
|
+
getNameManagerRows,
|
|
235
322
|
getRowSection,
|
|
323
|
+
getSheetTabMenuItems,
|
|
236
324
|
getSpreadsheetMenuItems,
|
|
325
|
+
getSpreadsheetScrollToCell,
|
|
326
|
+
getSpreadsheetViewWindow,
|
|
237
327
|
getTableSections,
|
|
328
|
+
getValidationListValues,
|
|
238
329
|
importFileIntoSpreadsheet,
|
|
239
330
|
isBlankValue,
|
|
240
331
|
isGeneralNumberFormat,
|
|
332
|
+
isLambdaDefinition,
|
|
241
333
|
isSingleCellRange,
|
|
242
334
|
mapFormulaReferences,
|
|
243
335
|
matchesFilterRule,
|
|
336
|
+
matchesTimePeriod,
|
|
337
|
+
measureSpreadsheetView,
|
|
338
|
+
nextSheetName,
|
|
244
339
|
normalizeRange,
|
|
245
340
|
numberFormatForCellFormat,
|
|
246
341
|
offsetFormulaReferences,
|
|
247
342
|
parseHtmlTable,
|
|
343
|
+
parseRuleRanges,
|
|
344
|
+
quoteSheetName,
|
|
248
345
|
rangeContains,
|
|
249
346
|
rangeContainsRange,
|
|
347
|
+
rangeDependencyKey,
|
|
348
|
+
rangesContain,
|
|
250
349
|
rangesIntersect,
|
|
251
350
|
readSpreadsheetClipboard,
|
|
252
351
|
rebaseClipboardRows,
|
|
253
352
|
registerSpreadsheetImportAdapters,
|
|
254
353
|
remapFormulaReferences,
|
|
354
|
+
renameNameInFormula,
|
|
355
|
+
renameSheetInFormula,
|
|
255
356
|
roundFloat,
|
|
256
357
|
rowPassesFilters,
|
|
358
|
+
ruleAnchor,
|
|
359
|
+
ruleFormulaAt,
|
|
257
360
|
runSpreadsheetMenuItem,
|
|
361
|
+
sameSpreadsheetViewWindow,
|
|
258
362
|
serializeHtmlTable,
|
|
363
|
+
sheetDropIndex,
|
|
364
|
+
sheetNameNeedsQuotes,
|
|
259
365
|
shiftFormulaReferences,
|
|
366
|
+
shiftRuleFormula,
|
|
367
|
+
shouldVirtualizeSpreadsheet,
|
|
368
|
+
subtractRange,
|
|
369
|
+
subtractRangeFromRanges,
|
|
260
370
|
toNumber,
|
|
261
|
-
tsvImportAdapter
|
|
262
|
-
|
|
371
|
+
tsvImportAdapter,
|
|
372
|
+
validateCellInput,
|
|
373
|
+
validateDefinedName,
|
|
374
|
+
validateSheetName
|
|
375
|
+
} from "./chunk-X7HXL2SB.js";
|
|
263
376
|
import {
|
|
264
377
|
escapeCsvField,
|
|
265
378
|
parseCsv,
|
|
@@ -276,9 +389,31 @@ import {
|
|
|
276
389
|
defaultIsEqual,
|
|
277
390
|
withoutDirty
|
|
278
391
|
} from "./chunk-2H7ZHPEJ.js";
|
|
392
|
+
import {
|
|
393
|
+
DEFAULT_TABLE_OPTIONS,
|
|
394
|
+
DEFAULT_TABLE_TOOLBAR,
|
|
395
|
+
EMPTY_TABLE_STATE,
|
|
396
|
+
MAX_TABLE_COLUMNS,
|
|
397
|
+
MAX_TABLE_ROWS,
|
|
398
|
+
TABLE_ACTIONS,
|
|
399
|
+
Table,
|
|
400
|
+
TableCell,
|
|
401
|
+
TableHeader,
|
|
402
|
+
TableRow,
|
|
403
|
+
createTableExtensions,
|
|
404
|
+
createTableStore,
|
|
405
|
+
getTableActionState,
|
|
406
|
+
getTableState,
|
|
407
|
+
isGfmTable,
|
|
408
|
+
isSelectionInTable,
|
|
409
|
+
isTableEnabled,
|
|
410
|
+
normalizeTableCellAlignment,
|
|
411
|
+
normalizeTableCellColor,
|
|
412
|
+
runTableAction,
|
|
413
|
+
shouldShowTableBubbleMenu
|
|
414
|
+
} from "./chunk-UBCFIABU.js";
|
|
279
415
|
import {
|
|
280
416
|
MARKDOWN_MENTION_SPLIT_REGEX,
|
|
281
|
-
MENTION_REGEX,
|
|
282
417
|
escapeHtml,
|
|
283
418
|
extractMentions,
|
|
284
419
|
extractMentionsFromDoc,
|
|
@@ -293,13 +428,22 @@ import {
|
|
|
293
428
|
preprocessMarkdownMentions,
|
|
294
429
|
sanitizeHtml,
|
|
295
430
|
stripMarkdownCode
|
|
296
|
-
} from "./chunk-
|
|
431
|
+
} from "./chunk-JOIREKL7.js";
|
|
432
|
+
import {
|
|
433
|
+
MENTION_REGEX,
|
|
434
|
+
findTextMentions,
|
|
435
|
+
formatMentionText,
|
|
436
|
+
setMentionRoleInText
|
|
437
|
+
} from "./chunk-O5RYH2PG.js";
|
|
297
438
|
import {
|
|
298
439
|
BLOCK_CHANGE_ATTRIBUTE,
|
|
299
440
|
CommentStore,
|
|
300
441
|
DELETION_MARK_NAME,
|
|
301
442
|
FORMAT_CHANGE_MARK_NAME,
|
|
302
443
|
INSERTION_MARK_NAME,
|
|
444
|
+
MOVE_FROM_CLASS,
|
|
445
|
+
MOVE_ID_ATTRIBUTE,
|
|
446
|
+
MOVE_TO_CLASS,
|
|
303
447
|
TRACK_CHANGES_SKIP_META,
|
|
304
448
|
TrackChanges,
|
|
305
449
|
TrackChangesStore,
|
|
@@ -314,15 +458,19 @@ import {
|
|
|
314
458
|
getTrackChangesStore,
|
|
315
459
|
getTrackedChangeAt,
|
|
316
460
|
getTrackedChanges,
|
|
461
|
+
isMoveSized,
|
|
317
462
|
isTrackChangesEnabled,
|
|
318
463
|
resolveTrackedChanges,
|
|
319
|
-
trackChangesPluginKey
|
|
320
|
-
|
|
464
|
+
trackChangesPluginKey,
|
|
465
|
+
trackedChangeLabel
|
|
466
|
+
} from "./chunk-SWE3NPOU.js";
|
|
321
467
|
import {
|
|
322
468
|
FORMULA_ERRORS,
|
|
323
469
|
FormulaEvaluator,
|
|
470
|
+
FormulaLambda,
|
|
324
471
|
FormulaParser,
|
|
325
472
|
MAX_FORMULA_ARRAY_SIZE,
|
|
473
|
+
MAX_LAMBDA_DEPTH,
|
|
326
474
|
MAX_NUMBER_FORMAT_CODE_CHARS,
|
|
327
475
|
NumberFormat,
|
|
328
476
|
WHOLE_COLUMN_END_ROW,
|
|
@@ -344,6 +492,7 @@ import {
|
|
|
344
492
|
getFormulaSignatureParts,
|
|
345
493
|
indexToColName,
|
|
346
494
|
isFormulaError,
|
|
495
|
+
isFormulaLambda,
|
|
347
496
|
listFormulaFunctions,
|
|
348
497
|
numberFormatColorToCss,
|
|
349
498
|
numberToText,
|
|
@@ -360,7 +509,7 @@ import {
|
|
|
360
509
|
tokenizeFormula,
|
|
361
510
|
unregisterFormulaFunction,
|
|
362
511
|
wildcardToRegExp
|
|
363
|
-
} from "./chunk-
|
|
512
|
+
} from "./chunk-ZRNHGAQT.js";
|
|
364
513
|
|
|
365
514
|
// src/controller.ts
|
|
366
515
|
import { Editor } from "@tiptap/core";
|
|
@@ -600,10 +749,1026 @@ var FileImportController = class {
|
|
|
600
749
|
function createFileImportController(getTarget, options) {
|
|
601
750
|
return new FileImportController(getTarget, options);
|
|
602
751
|
}
|
|
752
|
+
function summarizeImportStructure(outcomes) {
|
|
753
|
+
const reports = outcomes.map((outcome) => outcome.result?.structure).filter((report) => !!report);
|
|
754
|
+
if (!reports.length) return null;
|
|
755
|
+
const modes = new Set(reports.map((report) => report.mode));
|
|
756
|
+
const sum = (pick) => reports.reduce((total, report) => total + pick(report), 0);
|
|
757
|
+
return {
|
|
758
|
+
files: reports.length,
|
|
759
|
+
mode: modes.size > 1 ? "mixed" : reports[0].mode,
|
|
760
|
+
headings: sum((r) => r.counts.headings),
|
|
761
|
+
lists: sum((r) => r.counts.lists),
|
|
762
|
+
tables: sum((r) => r.counts.tables),
|
|
763
|
+
paragraphs: sum((r) => r.counts.paragraphs),
|
|
764
|
+
multiColumnPages: sum((r) => r.multiColumnPages),
|
|
765
|
+
confidence: Math.round(sum((r) => r.confidence) / reports.length * 100) / 100
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// src/import/pdf-layout.ts
|
|
770
|
+
var MAX_COLS = 63;
|
|
771
|
+
var MAX_TABLE_ROWS2 = 2e3;
|
|
772
|
+
var MAX_RULES = 2e3;
|
|
773
|
+
var MAX_DEPTH = 4;
|
|
774
|
+
var BULLET_GLYPH_RE = /^[•◦▪▫●○■□‣⁃∙·➢►▶✓✔❖]\s*/;
|
|
775
|
+
var BULLET_DASH_RE = /^[-–—*]\s+/;
|
|
776
|
+
var ORDERED_RE = /^(?:\((\d{1,3}|[a-zA-Z]|[ivxlcIVXLC]{1,6})\)|(\d{1,3}|[a-zA-Z]|[ivxlcIVXLC]{1,6})[.)])\s+/;
|
|
777
|
+
var MARKER_ONLY_RE = /^(?:[•◦▪▫●○■□‣⁃∙·➢►▶✓✔❖]|\(?(?:\d{1,3}|[a-zA-Z]|[ivxlcIVXLC]{1,6})[.)])$/;
|
|
778
|
+
var PAGE_NUMBER_RE = /^(?:page\s+)?(?:\d{1,4}|[ivxlcdm]{1,7})(?:\s*(?:of|\/)\s*\d{1,4})?$/i;
|
|
779
|
+
var DASHED_PAGE_NUMBER_RE = /^[-–—]\s*\d{1,4}\s*[-–—]$/;
|
|
780
|
+
var SENTENCE_END_RE = /[.!?:;]["'”’)\]]?$/;
|
|
781
|
+
var BOLD_FONT_RE = /bold|black|heavy|semibold|demi/i;
|
|
782
|
+
var ITALIC_FONT_RE = /italic|oblique/i;
|
|
783
|
+
function minOf(list, fn) {
|
|
784
|
+
let min = Infinity;
|
|
785
|
+
for (const item of list) min = Math.min(min, fn(item));
|
|
786
|
+
return min;
|
|
787
|
+
}
|
|
788
|
+
function maxOf(list, fn) {
|
|
789
|
+
let max = -Infinity;
|
|
790
|
+
for (const item of list) max = Math.max(max, fn(item));
|
|
791
|
+
return max;
|
|
792
|
+
}
|
|
793
|
+
function lowerBound(values, target) {
|
|
794
|
+
let lo = 0;
|
|
795
|
+
let hi = values.length;
|
|
796
|
+
while (lo < hi) {
|
|
797
|
+
const mid = lo + hi >> 1;
|
|
798
|
+
if (values[mid] < target) lo = mid + 1;
|
|
799
|
+
else hi = mid;
|
|
800
|
+
}
|
|
801
|
+
return lo;
|
|
802
|
+
}
|
|
803
|
+
function median(values) {
|
|
804
|
+
if (!values.length) return 0;
|
|
805
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
806
|
+
const mid = sorted.length >> 1;
|
|
807
|
+
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
808
|
+
}
|
|
809
|
+
var countWords = (text) => {
|
|
810
|
+
let words = 0;
|
|
811
|
+
let inWord = false;
|
|
812
|
+
for (let i = 0; i < text.length; i++) {
|
|
813
|
+
const space = text.charCodeAt(i) <= 32;
|
|
814
|
+
if (!space && !inWord) words++;
|
|
815
|
+
inWord = !space;
|
|
816
|
+
}
|
|
817
|
+
return words;
|
|
818
|
+
};
|
|
819
|
+
var collapse = (text) => text.replace(/\s+/g, " ").trim();
|
|
820
|
+
function runSize(run) {
|
|
821
|
+
if (run.fontSize && run.fontSize > 0) return run.fontSize;
|
|
822
|
+
if (run.height && run.height > 0) return run.height;
|
|
823
|
+
return 10;
|
|
824
|
+
}
|
|
825
|
+
function buildFragments(runs) {
|
|
826
|
+
const items = runs.filter((run) => typeof run.text === "string" && run.text.trim() !== "" && Number.isFinite(run.x) && Number.isFinite(run.y)).map((run) => {
|
|
827
|
+
const size = runSize(run);
|
|
828
|
+
const width = run.width !== void 0 && run.width >= 0 ? run.width : run.text.length * size * 0.5;
|
|
829
|
+
return {
|
|
830
|
+
text: run.text,
|
|
831
|
+
x0: run.x,
|
|
832
|
+
x1: run.x + width,
|
|
833
|
+
y: run.y,
|
|
834
|
+
size,
|
|
835
|
+
bold: run.bold ?? BOLD_FONT_RE.test(run.fontName ?? ""),
|
|
836
|
+
italic: run.italic ?? ITALIC_FONT_RE.test(run.fontName ?? "")
|
|
837
|
+
};
|
|
838
|
+
});
|
|
839
|
+
items.sort((a, b) => b.y - a.y || a.x0 - b.x0);
|
|
840
|
+
const frags = [];
|
|
841
|
+
let i = 0;
|
|
842
|
+
while (i < items.length) {
|
|
843
|
+
const anchor = items[i];
|
|
844
|
+
let j = i + 1;
|
|
845
|
+
while (j < items.length && anchor.y - items[j].y <= Math.max(1, Math.min(anchor.size, items[j].size) * 0.5)) j++;
|
|
846
|
+
const row = items.slice(i, j).sort((a, b) => a.x0 - b.x0);
|
|
847
|
+
i = j;
|
|
848
|
+
let current = null;
|
|
849
|
+
const finish = () => {
|
|
850
|
+
if (!current) return;
|
|
851
|
+
let best = "";
|
|
852
|
+
let bestChars = -1;
|
|
853
|
+
current.styleChars.forEach((chars, key) => {
|
|
854
|
+
if (chars > bestChars) {
|
|
855
|
+
best = key;
|
|
856
|
+
bestChars = chars;
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
const [size, bold, italic] = best.split("|");
|
|
860
|
+
current.size = Number(size);
|
|
861
|
+
current.bold = bold === "1";
|
|
862
|
+
current.italic = italic === "1";
|
|
863
|
+
current.text = collapse(current.text);
|
|
864
|
+
current.words = countWords(current.text);
|
|
865
|
+
current.top = current.y + current.size * 0.8;
|
|
866
|
+
current.bottom = current.y - current.size * 0.2;
|
|
867
|
+
if (current.text) frags.push(current);
|
|
868
|
+
current = null;
|
|
869
|
+
};
|
|
870
|
+
for (const item of row) {
|
|
871
|
+
if (current) {
|
|
872
|
+
const gap = item.x0 - current.x1;
|
|
873
|
+
const em = Math.max(current.size, item.size);
|
|
874
|
+
const markerOnly = MARKER_ONLY_RE.test(collapse(current.text));
|
|
875
|
+
if (gap > em * (markerOnly ? 6 : 1)) finish();
|
|
876
|
+
}
|
|
877
|
+
if (!current) {
|
|
878
|
+
current = {
|
|
879
|
+
text: item.text,
|
|
880
|
+
x0: item.x0,
|
|
881
|
+
x1: item.x1,
|
|
882
|
+
y: item.y,
|
|
883
|
+
top: 0,
|
|
884
|
+
bottom: 0,
|
|
885
|
+
size: item.size,
|
|
886
|
+
bold: item.bold,
|
|
887
|
+
italic: item.italic,
|
|
888
|
+
words: 0,
|
|
889
|
+
styleChars: /* @__PURE__ */ new Map()
|
|
890
|
+
};
|
|
891
|
+
} else {
|
|
892
|
+
const gap = item.x0 - current.x1;
|
|
893
|
+
if (gap > Math.max(current.size, item.size) * 0.15 && !/\s$/.test(current.text) && !/^\s/.test(item.text)) {
|
|
894
|
+
current.text += " ";
|
|
895
|
+
}
|
|
896
|
+
current.text += item.text;
|
|
897
|
+
current.x1 = Math.max(current.x1, item.x1);
|
|
898
|
+
}
|
|
899
|
+
const key = `${Math.round(item.size * 2) / 2}|${item.bold ? 1 : 0}|${item.italic ? 1 : 0}`;
|
|
900
|
+
current.styleChars.set(key, (current.styleChars.get(key) ?? 0) + item.text.trim().length);
|
|
901
|
+
}
|
|
902
|
+
finish();
|
|
903
|
+
}
|
|
904
|
+
return frags;
|
|
905
|
+
}
|
|
906
|
+
function baselineRows(frags) {
|
|
907
|
+
const rows = [];
|
|
908
|
+
for (const frag of frags) {
|
|
909
|
+
const row = rows[rows.length - 1];
|
|
910
|
+
if (row && Math.abs(row[0].y - frag.y) <= Math.max(1, Math.min(row[0].size, frag.size) * 0.5)) row.push(frag);
|
|
911
|
+
else rows.push([frag]);
|
|
912
|
+
}
|
|
913
|
+
return rows;
|
|
914
|
+
}
|
|
915
|
+
var edgeKey = (row) => collapse(row.map((f) => f.text).join(" ")).toLowerCase().replace(/\d+/g, "#");
|
|
916
|
+
function removeHeadersAndFooters(pages) {
|
|
917
|
+
const removed = { headers: 0, footers: 0, pageNumbers: 0 };
|
|
918
|
+
const pageRows = pages.map((frags) => baselineRows([...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0)));
|
|
919
|
+
const counts = /* @__PURE__ */ new Map();
|
|
920
|
+
const candidates = [];
|
|
921
|
+
pageRows.forEach((rows, page) => {
|
|
922
|
+
const n = rows.length;
|
|
923
|
+
const picks = [];
|
|
924
|
+
for (let k = 0; k < Math.min(2, n); k++) picks.push([k, "top"]);
|
|
925
|
+
for (let k = Math.max(Math.min(2, n), n - 2); k < n; k++) picks.push([k, "bottom"]);
|
|
926
|
+
for (const [index, edge] of picks) {
|
|
927
|
+
const row = rows[index];
|
|
928
|
+
const extreme = edge === "top" ? index === 0 : index === n - 1;
|
|
929
|
+
const neighbour = edge === "top" ? rows[index + 1] : rows[index - 1];
|
|
930
|
+
const gap = neighbour ? Math.abs(row[0].y - neighbour[0].y) / row[0].size : Infinity;
|
|
931
|
+
candidates.push({ page, row, edge, extreme, gap });
|
|
932
|
+
const key = `${edge}:${edgeKey(row)}`;
|
|
933
|
+
if (!counts.has(key)) counts.set(key, /* @__PURE__ */ new Set());
|
|
934
|
+
counts.get(key).add(page);
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
const minPages = Math.max(2, Math.ceil(pages.length * 0.5));
|
|
938
|
+
const drop = /* @__PURE__ */ new Set();
|
|
939
|
+
for (const candidate of candidates) {
|
|
940
|
+
const text = collapse(candidate.row.map((f) => f.text).join(" "));
|
|
941
|
+
const isPageNumber = candidate.extreme && (PAGE_NUMBER_RE.test(text) || DASHED_PAGE_NUMBER_RE.test(text));
|
|
942
|
+
const repeated = (counts.get(`${candidate.edge}:${edgeKey(candidate.row)}`)?.size ?? 0) >= minPages;
|
|
943
|
+
let kind = null;
|
|
944
|
+
if (isPageNumber && (pages.length > 1 || candidate.gap > 2.5)) kind = "pageNumbers";
|
|
945
|
+
else if (repeated && pages.length > 1) kind = candidate.edge === "top" ? "headers" : "footers";
|
|
946
|
+
if (!kind || candidate.row.some((f) => drop.has(f))) continue;
|
|
947
|
+
candidate.row.forEach((f) => drop.add(f));
|
|
948
|
+
removed[kind]++;
|
|
949
|
+
}
|
|
950
|
+
if (drop.size) {
|
|
951
|
+
pages.forEach((frags, index) => {
|
|
952
|
+
pages[index] = frags.filter((f) => !drop.has(f));
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
return removed;
|
|
956
|
+
}
|
|
957
|
+
function splitRules(rules) {
|
|
958
|
+
const h = [];
|
|
959
|
+
const v = [];
|
|
960
|
+
for (const rule of rules.slice(0, MAX_RULES)) {
|
|
961
|
+
const { x1, y1, x2, y2 } = rule;
|
|
962
|
+
if (![x1, y1, x2, y2].every(Number.isFinite)) continue;
|
|
963
|
+
const dx = Math.abs(x2 - x1);
|
|
964
|
+
const dy = Math.abs(y2 - y1);
|
|
965
|
+
if (dy <= 1.5 && dx >= 6) h.push({ y: (y1 + y2) / 2, x0: Math.min(x1, x2), x1: Math.max(x1, x2) });
|
|
966
|
+
else if (dx <= 1.5 && dy >= 6) v.push({ x: (x1 + x2) / 2, y0: Math.min(y1, y2), y1: Math.max(y1, y2) });
|
|
967
|
+
}
|
|
968
|
+
return { h, v };
|
|
969
|
+
}
|
|
970
|
+
function clusterValues(values, tol) {
|
|
971
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
972
|
+
const out = [];
|
|
973
|
+
for (const value of sorted) {
|
|
974
|
+
const cluster = out[out.length - 1];
|
|
975
|
+
if (cluster && value - cluster.last <= tol) {
|
|
976
|
+
cluster.sum += value;
|
|
977
|
+
cluster.n++;
|
|
978
|
+
cluster.last = value;
|
|
979
|
+
} else out.push({ sum: value, n: 1, last: value });
|
|
980
|
+
}
|
|
981
|
+
return out.map((c) => c.sum / c.n);
|
|
982
|
+
}
|
|
983
|
+
function find(parent, i) {
|
|
984
|
+
while (parent[i] !== i) {
|
|
985
|
+
parent[i] = parent[parent[i]];
|
|
986
|
+
i = parent[i];
|
|
987
|
+
}
|
|
988
|
+
return i;
|
|
989
|
+
}
|
|
990
|
+
var cellText = (frags, dehyphenate, stats) => {
|
|
991
|
+
const sorted = [...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0);
|
|
992
|
+
let text = "";
|
|
993
|
+
let lastY = Infinity;
|
|
994
|
+
for (const frag of sorted) {
|
|
995
|
+
if (!text) text = frag.text;
|
|
996
|
+
else if (Math.abs(lastY - frag.y) > frag.size * 0.5) text = joinLines(text, frag.text, dehyphenate, stats);
|
|
997
|
+
else text += ` ${frag.text}`;
|
|
998
|
+
lastY = frag.y;
|
|
999
|
+
}
|
|
1000
|
+
return collapse(text);
|
|
1001
|
+
};
|
|
1002
|
+
var NUMERIC_RE = /^[-+−(]?[$€£¥]?\s?\d[\d,.\s]*%?\)?$/;
|
|
1003
|
+
function headerRowCount(rowFrags) {
|
|
1004
|
+
if (rowFrags.length < 2) return 0;
|
|
1005
|
+
const cells = (row) => row.filter((cell) => cell.length > 0);
|
|
1006
|
+
const first = cells(rowFrags[0]);
|
|
1007
|
+
if (!first.length) return 0;
|
|
1008
|
+
const rest = rowFrags.slice(1).flatMap(cells);
|
|
1009
|
+
const allBold = (list) => list.length > 0 && list.every((cell) => cell.every((f) => f.bold));
|
|
1010
|
+
if (allBold(first) && !allBold(rest)) return 1;
|
|
1011
|
+
const numeric = (cell) => NUMERIC_RE.test(collapse(cell.map((f) => f.text).join(" ")));
|
|
1012
|
+
if (first.every((cell) => !numeric(cell))) {
|
|
1013
|
+
const columns = rowFrags[0].length;
|
|
1014
|
+
for (let c = 0; c < columns; c++) {
|
|
1015
|
+
const body = rowFrags.slice(1).map((row) => row[c]).filter((cell) => cell && cell.length > 0);
|
|
1016
|
+
if (rowFrags[0][c].length && body.length >= 2 && body.every(numeric)) return 1;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
const firstSize = maxOf(first.flat(), (f) => f.size);
|
|
1020
|
+
const restSize = median(rest.flat().map((f) => f.size));
|
|
1021
|
+
if (restSize > 0 && firstSize >= restSize * 1.1) return 1;
|
|
1022
|
+
return 0;
|
|
1023
|
+
}
|
|
1024
|
+
function ruledTables(frags, rules, page, dehyphenate, stats) {
|
|
1025
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
1026
|
+
const atoms = [];
|
|
1027
|
+
const { h, v } = splitRules(rules);
|
|
1028
|
+
if (h.length < 2) return { atoms, consumed };
|
|
1029
|
+
const n = h.length + v.length;
|
|
1030
|
+
const parent = Array.from({ length: n }, (_, i) => i);
|
|
1031
|
+
const union = (a, b) => {
|
|
1032
|
+
const ra = find(parent, a);
|
|
1033
|
+
const rb = find(parent, b);
|
|
1034
|
+
if (ra !== rb) parent[ra] = rb;
|
|
1035
|
+
};
|
|
1036
|
+
const tol = 2;
|
|
1037
|
+
const vOrder = v.map((_, i) => i).sort((a, b) => v[a].x - v[b].x);
|
|
1038
|
+
const vxs = vOrder.map((i) => v[i].x);
|
|
1039
|
+
h.forEach((seg, hi) => {
|
|
1040
|
+
let lo = 0;
|
|
1041
|
+
let hiIdx = vxs.length;
|
|
1042
|
+
while (lo < hiIdx) {
|
|
1043
|
+
const mid = lo + hiIdx >> 1;
|
|
1044
|
+
if (vxs[mid] < seg.x0 - tol) lo = mid + 1;
|
|
1045
|
+
else hiIdx = mid;
|
|
1046
|
+
}
|
|
1047
|
+
for (let k = lo; k < vxs.length && vxs[k] <= seg.x1 + tol; k++) {
|
|
1048
|
+
const vs = v[vOrder[k]];
|
|
1049
|
+
if (seg.y >= vs.y0 - tol && seg.y <= vs.y1 + tol) union(hi, h.length + vOrder[k]);
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
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);
|
|
1053
|
+
for (let k = 1; k < hOrder.length; k++) {
|
|
1054
|
+
const a = h[hOrder[k - 1]];
|
|
1055
|
+
const b = h[hOrder[k]];
|
|
1056
|
+
if (Math.abs(a.x0 - b.x0) <= 4 && Math.abs(a.x1 - b.x1) <= 4) union(hOrder[k - 1], hOrder[k]);
|
|
1057
|
+
}
|
|
1058
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1059
|
+
h.forEach((seg, i) => {
|
|
1060
|
+
const root = find(parent, i);
|
|
1061
|
+
if (!groups.has(root)) groups.set(root, { h: [], v: [] });
|
|
1062
|
+
groups.get(root).h.push(seg);
|
|
1063
|
+
});
|
|
1064
|
+
v.forEach((seg, i) => {
|
|
1065
|
+
const root = find(parent, h.length + i);
|
|
1066
|
+
groups.get(root)?.v.push(seg);
|
|
1067
|
+
});
|
|
1068
|
+
const byY = [...frags].sort((a, b) => a.y - b.y);
|
|
1069
|
+
const ys = byY.map((f) => f.y);
|
|
1070
|
+
const inRange = (y0, y1) => {
|
|
1071
|
+
let lo = 0;
|
|
1072
|
+
let hi = ys.length;
|
|
1073
|
+
while (lo < hi) {
|
|
1074
|
+
const mid = lo + hi >> 1;
|
|
1075
|
+
if (ys[mid] < y0) lo = mid + 1;
|
|
1076
|
+
else hi = mid;
|
|
1077
|
+
}
|
|
1078
|
+
const out = [];
|
|
1079
|
+
for (let k = lo; k < ys.length && ys[k] <= y1; k++) out.push(byY[k]);
|
|
1080
|
+
return out;
|
|
1081
|
+
};
|
|
1082
|
+
groups.forEach((group) => {
|
|
1083
|
+
const hys = clusterValues(group.h.map((s) => s.y), 1.5).sort((a, b) => b - a);
|
|
1084
|
+
if (hys.length < 2) return;
|
|
1085
|
+
const x0 = Math.min(...group.h.map((s) => s.x0), ...group.v.map((s) => s.x));
|
|
1086
|
+
const x1 = Math.max(...group.h.map((s) => s.x1), ...group.v.map((s) => s.x));
|
|
1087
|
+
const top = Math.max(hys[0], ...group.v.map((s) => s.y1));
|
|
1088
|
+
const bottom = Math.min(hys[hys.length - 1], ...group.v.map((s) => s.y0));
|
|
1089
|
+
const inside = inRange(bottom, top).filter((f) => {
|
|
1090
|
+
if (consumed.has(f)) return false;
|
|
1091
|
+
const cx = (f.x0 + f.x1) / 2;
|
|
1092
|
+
return cx >= x0 - 1 && cx <= x1 + 1;
|
|
1093
|
+
});
|
|
1094
|
+
if (inside.length < 2) return;
|
|
1095
|
+
const vxsGroup = clusterValues(group.v.map((s) => s.x), 1.5);
|
|
1096
|
+
let table = null;
|
|
1097
|
+
if (vxsGroup.length >= 3 || vxsGroup.length >= 2 && hys.length >= 3 && vxsGroup.some((x) => x > x0 + 4 && x < x1 - 4)) {
|
|
1098
|
+
table = gridTable(inside, group, hys, vxsGroup, x0, x1, top, bottom, page, dehyphenate, stats);
|
|
1099
|
+
}
|
|
1100
|
+
if (!table) {
|
|
1101
|
+
const result = alignedTable(inside, page, 2, dehyphenate, stats, hys.length >= 3 ? hys[1] : void 0);
|
|
1102
|
+
if (result && !result.leftover.length && !result.before.length) table = { ...result.table, ruled: true, confidence: 0.85 };
|
|
1103
|
+
}
|
|
1104
|
+
if (!table) return;
|
|
1105
|
+
inside.forEach((f) => consumed.add(f));
|
|
1106
|
+
atoms.push({
|
|
1107
|
+
text: "",
|
|
1108
|
+
x0,
|
|
1109
|
+
x1,
|
|
1110
|
+
y: bottom,
|
|
1111
|
+
top,
|
|
1112
|
+
bottom,
|
|
1113
|
+
size: median(inside.map((f) => f.size)),
|
|
1114
|
+
bold: false,
|
|
1115
|
+
italic: false,
|
|
1116
|
+
words: 0,
|
|
1117
|
+
table
|
|
1118
|
+
});
|
|
1119
|
+
});
|
|
1120
|
+
return { atoms, consumed };
|
|
1121
|
+
}
|
|
1122
|
+
function gridTable(inside, group, hys, vxsIn, x0, x1, top, bottom, page, dehyphenate, stats) {
|
|
1123
|
+
const xs = [...vxsIn];
|
|
1124
|
+
if (xs[0] > x0 + 4) xs.unshift(x0);
|
|
1125
|
+
if (xs[xs.length - 1] < x1 - 4) xs.push(x1);
|
|
1126
|
+
const rowsY = [...hys];
|
|
1127
|
+
if (rowsY[0] < top - 4) rowsY.unshift(top);
|
|
1128
|
+
if (rowsY[rowsY.length - 1] > bottom + 4) rowsY.push(bottom);
|
|
1129
|
+
const cols = xs.length - 1;
|
|
1130
|
+
const rows = rowsY.length - 1;
|
|
1131
|
+
if (cols < 2 || rows < 1 || cols > MAX_COLS || rows > MAX_TABLE_ROWS2) return null;
|
|
1132
|
+
const grid = Array.from({ length: rows }, () => Array.from({ length: cols }, () => []));
|
|
1133
|
+
const ascRows = [...rowsY].reverse();
|
|
1134
|
+
for (const frag of inside) {
|
|
1135
|
+
const x = frag.x0 + Math.min(2, (frag.x1 - frag.x0) / 2);
|
|
1136
|
+
const c = lowerBound(xs, x + 1e-9) - 1;
|
|
1137
|
+
const yProbe = frag.y + frag.size * 0.3;
|
|
1138
|
+
const r = rows - (lowerBound(ascRows, yProbe + 1e-9) - 1) - 1;
|
|
1139
|
+
if (c >= 0 && c < cols && r >= 0 && r < rows) grid[r][c].push(frag);
|
|
1140
|
+
}
|
|
1141
|
+
const filled = grid.flat().filter((cell) => cell.length).length;
|
|
1142
|
+
if (filled < 2 || rows < 2 && cols < 2) return null;
|
|
1143
|
+
const vAt = xs.map(() => []);
|
|
1144
|
+
for (const seg of group.v) {
|
|
1145
|
+
const k = lowerBound(xs, seg.x - 2);
|
|
1146
|
+
if (k < xs.length && Math.abs(xs[k] - seg.x) <= 2) vAt[k].push(seg);
|
|
1147
|
+
}
|
|
1148
|
+
const hAt = rowsY.map(() => []);
|
|
1149
|
+
for (const seg of group.h) {
|
|
1150
|
+
const k = rows - lowerBound(ascRows, seg.y - 2);
|
|
1151
|
+
if (k >= 0 && k <= rows && Math.abs(rowsY[k] - seg.y) <= 2) hAt[k].push(seg);
|
|
1152
|
+
}
|
|
1153
|
+
const hasV = (k, y) => vAt[k].some((s) => y >= s.y0 - 2 && y <= s.y1 + 2);
|
|
1154
|
+
const hasH = (k, x) => hAt[k].some((s) => x >= s.x0 - 2 && x <= s.x1 + 2);
|
|
1155
|
+
const covered = grid.map((row) => row.map(() => false));
|
|
1156
|
+
const header = headerRowCount(grid);
|
|
1157
|
+
const out = [];
|
|
1158
|
+
for (let r = 0; r < rows; r++) {
|
|
1159
|
+
const midY = (rowsY[r] + rowsY[r + 1]) / 2;
|
|
1160
|
+
const row = [];
|
|
1161
|
+
for (let c = 0; c < cols; c++) {
|
|
1162
|
+
if (covered[r][c]) continue;
|
|
1163
|
+
let colSpan = 1;
|
|
1164
|
+
while (c + colSpan < cols && !hasV(c + colSpan, midY) && !grid[r][c + colSpan].length && !covered[r][c + colSpan]) colSpan++;
|
|
1165
|
+
let rowSpan = 1;
|
|
1166
|
+
const midX = (xs[c] + xs[c + colSpan]) / 2;
|
|
1167
|
+
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)) {
|
|
1168
|
+
rowSpan++;
|
|
1169
|
+
}
|
|
1170
|
+
for (let rr = r; rr < r + rowSpan; rr++) for (let cc = c; cc < c + colSpan; cc++) covered[rr][cc] = true;
|
|
1171
|
+
row.push({ text: cellText(grid[r][c], dehyphenate, stats), colSpan, rowSpan, header: r < header });
|
|
1172
|
+
}
|
|
1173
|
+
out.push(row);
|
|
1174
|
+
}
|
|
1175
|
+
return { type: "table", page, confidence: 0.95, ruled: true, rows: out, columns: cols, headerRows: header };
|
|
1176
|
+
}
|
|
1177
|
+
function alignedTable(frags, page, minRows, dehyphenate, stats, headerRuleY) {
|
|
1178
|
+
const sorted = [...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0);
|
|
1179
|
+
let rows = baselineRows(sorted).map((row) => row.sort((a, b) => a.x0 - b.x0));
|
|
1180
|
+
if (rows.length < minRows) return null;
|
|
1181
|
+
const multi = rows.filter((row) => row.length >= 2);
|
|
1182
|
+
if (multi.length < Math.min(minRows, 2)) return null;
|
|
1183
|
+
const spans = multi.flat().map((f) => [f.x0, f.x1]).sort((a, b) => a[0] - b[0]);
|
|
1184
|
+
const merged = [];
|
|
1185
|
+
for (const [a, b] of spans) {
|
|
1186
|
+
const last = merged[merged.length - 1];
|
|
1187
|
+
if (last && a <= last[1] + 1) last[1] = Math.max(last[1], b);
|
|
1188
|
+
else merged.push([a, b]);
|
|
1189
|
+
}
|
|
1190
|
+
if (merged.length < 2 || merged.length > MAX_COLS) return null;
|
|
1191
|
+
const edges = merged.map((m) => m[0]);
|
|
1192
|
+
const cols = merged.length;
|
|
1193
|
+
const colOf = (x) => {
|
|
1194
|
+
let c = 0;
|
|
1195
|
+
while (c + 1 < cols && x >= merged[c + 1][0] - 1) c++;
|
|
1196
|
+
return c;
|
|
1197
|
+
};
|
|
1198
|
+
const spanOf = (f, c) => {
|
|
1199
|
+
let span = 1;
|
|
1200
|
+
while (c + span < cols && f.x1 > merged[c + span][0] + 2) span++;
|
|
1201
|
+
return span;
|
|
1202
|
+
};
|
|
1203
|
+
const rowIsCells = (row) => {
|
|
1204
|
+
if (row.length >= 2) return true;
|
|
1205
|
+
const f = row[0];
|
|
1206
|
+
const c = colOf(f.x0);
|
|
1207
|
+
return spanOf(f, c) >= 2 && f.words <= 8 && Math.abs(f.x0 - edges[c]) <= Math.max(4, f.size * 0.6);
|
|
1208
|
+
};
|
|
1209
|
+
const before = [];
|
|
1210
|
+
const leftover = [];
|
|
1211
|
+
let first = 0;
|
|
1212
|
+
let end = rows.length;
|
|
1213
|
+
while (first < end && !rowIsCells(rows[first])) first++;
|
|
1214
|
+
while (end > first && !rowIsCells(rows[end - 1])) end--;
|
|
1215
|
+
rows.slice(0, first).forEach((row) => before.push(...row));
|
|
1216
|
+
rows.slice(end).forEach((row) => leftover.push(...row));
|
|
1217
|
+
rows = rows.slice(first, end);
|
|
1218
|
+
if (rows.length < minRows || rows.length > MAX_TABLE_ROWS2) return null;
|
|
1219
|
+
const grid = [];
|
|
1220
|
+
const spansGrid = [];
|
|
1221
|
+
let prevRow = null;
|
|
1222
|
+
for (const row of rows) {
|
|
1223
|
+
const cells = Array.from({ length: cols }, () => []);
|
|
1224
|
+
const spanRow = Array.from({ length: cols }, () => 1);
|
|
1225
|
+
for (const f of row) {
|
|
1226
|
+
const c = colOf(f.x0);
|
|
1227
|
+
cells[c].push(f);
|
|
1228
|
+
spanRow[c] = Math.max(spanRow[c], row.length === 1 ? spanOf(f, c) : 1);
|
|
1229
|
+
}
|
|
1230
|
+
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;
|
|
1231
|
+
if (continuation) {
|
|
1232
|
+
cells.forEach((cell, c) => grid[grid.length - 1][c].push(...cell));
|
|
1233
|
+
} else {
|
|
1234
|
+
grid.push(cells);
|
|
1235
|
+
spansGrid.push(spanRow);
|
|
1236
|
+
}
|
|
1237
|
+
prevRow = row;
|
|
1238
|
+
}
|
|
1239
|
+
if (grid.length < minRows) return null;
|
|
1240
|
+
const full = grid.filter((cells) => cells.filter((c) => c.length).length >= 2).length;
|
|
1241
|
+
if (full / grid.length < 0.6) return null;
|
|
1242
|
+
const cellsWithText = grid.flat().filter((c) => c.length);
|
|
1243
|
+
const meanWords = cellsWithText.reduce((sum, cell) => sum + cell.reduce((s, f) => s + f.words, 0), 0) / cellsWithText.length;
|
|
1244
|
+
if (meanWords > 12) return null;
|
|
1245
|
+
let header = headerRowCount(grid);
|
|
1246
|
+
if (headerRuleY !== void 0) {
|
|
1247
|
+
const above = rows.filter((row) => row[0].y > headerRuleY).length;
|
|
1248
|
+
if (above > 0 && above < grid.length) header = Math.max(header, Math.min(above, grid.length - 1));
|
|
1249
|
+
}
|
|
1250
|
+
const out = grid.map((cells, r) => {
|
|
1251
|
+
const row = [];
|
|
1252
|
+
for (let c = 0; c < cols; ) {
|
|
1253
|
+
const span = Math.min(spansGrid[r][c], cols - c);
|
|
1254
|
+
row.push({ text: cellText(cells[c], dehyphenate, stats), colSpan: span, rowSpan: 1, header: r < header });
|
|
1255
|
+
c += span;
|
|
1256
|
+
}
|
|
1257
|
+
return row;
|
|
1258
|
+
});
|
|
1259
|
+
const confidence = Math.min(
|
|
1260
|
+
0.9,
|
|
1261
|
+
0.5 + (grid.length >= 5 ? 0.1 : 0) + (cols >= 3 ? 0.1 : 0) + 0.2 * (full / grid.length) - (cols === 2 ? 0.05 : 0)
|
|
1262
|
+
);
|
|
1263
|
+
return {
|
|
1264
|
+
table: { type: "table", page, confidence, ruled: false, rows: out, columns: cols, headerRows: header },
|
|
1265
|
+
leftover,
|
|
1266
|
+
before
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
function readingOrder(items, body, detectColumns, depth, columnPages) {
|
|
1270
|
+
const byTop = [...items].sort((a, b) => b.top - a.top || a.x0 - b.x0);
|
|
1271
|
+
if (!detectColumns || items.length < 2 || depth > MAX_DEPTH) return [{ kind: "flow", items: byTop }];
|
|
1272
|
+
const left = minOf(items, (f) => f.x0);
|
|
1273
|
+
const right = maxOf(items, (f) => f.x1);
|
|
1274
|
+
const width = right - left;
|
|
1275
|
+
const isNarrow = (f) => f.x1 - f.x0 < width * 0.55;
|
|
1276
|
+
const narrow = items.filter(isNarrow);
|
|
1277
|
+
const minGutter = Math.max(body * 0.9, 6);
|
|
1278
|
+
const allowed = Math.max(1, Math.floor(narrow.length * 0.08));
|
|
1279
|
+
const events = [];
|
|
1280
|
+
for (const f of narrow) events.push([f.x0, 1], [f.x1, -1]);
|
|
1281
|
+
events.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
1282
|
+
const candidates = [];
|
|
1283
|
+
let depthNow = 0;
|
|
1284
|
+
let seenContent = false;
|
|
1285
|
+
let start = null;
|
|
1286
|
+
for (const [x, delta] of events) {
|
|
1287
|
+
depthNow += delta;
|
|
1288
|
+
if (depthNow > allowed) {
|
|
1289
|
+
if (start !== null && seenContent && x - start >= minGutter) candidates.push([start, x]);
|
|
1290
|
+
start = null;
|
|
1291
|
+
seenContent = true;
|
|
1292
|
+
} else if (start === null) start = x;
|
|
1293
|
+
}
|
|
1294
|
+
const ends = narrow.map((f) => f.x1).sort((a, b) => a - b);
|
|
1295
|
+
const starts = narrow.map((f) => f.x0).sort((a, b) => a - b);
|
|
1296
|
+
const gutters = [];
|
|
1297
|
+
for (const [a, b] of candidates) {
|
|
1298
|
+
const endBelow = lowerBound(ends, b) - 1;
|
|
1299
|
+
const left2 = endBelow >= 0 && ends[endBelow] > a ? ends[endBelow] : a;
|
|
1300
|
+
const startAbove = lowerBound(starts, a + 1e-9);
|
|
1301
|
+
const right2 = startAbove < starts.length && starts[startAbove] < b ? starts[startAbove] : b;
|
|
1302
|
+
if (right2 - left2 < minGutter) continue;
|
|
1303
|
+
const onLeft = lowerBound(ends, left2 + 1e-6);
|
|
1304
|
+
const onRight = starts.length - lowerBound(starts, right2 - 1e-6);
|
|
1305
|
+
const strays = narrow.length - onLeft - onRight;
|
|
1306
|
+
if (strays < Math.min(onLeft, onRight)) gutters.push([left2, right2]);
|
|
1307
|
+
}
|
|
1308
|
+
if (!gutters.length) return [{ kind: "flow", items: byTop }];
|
|
1309
|
+
const gutterEnds = gutters.map((g) => g[1]);
|
|
1310
|
+
const crosses = (f) => {
|
|
1311
|
+
const k = lowerBound(gutterEnds, f.x0 + 1 + 1e-9);
|
|
1312
|
+
return k < gutters.length && f.x1 > gutters[k][0] + 1 && f.x0 < gutters[k][1] - 1;
|
|
1313
|
+
};
|
|
1314
|
+
const columnOf = (f) => lowerBound(gutterEnds, f.x0 + 1 + 1e-9);
|
|
1315
|
+
const bands = [];
|
|
1316
|
+
for (const f of byTop) {
|
|
1317
|
+
const spanning = crosses(f);
|
|
1318
|
+
const band = bands[bands.length - 1];
|
|
1319
|
+
if (band && band.spanning === spanning) band.items.push(f);
|
|
1320
|
+
else bands.push({ spanning, items: [f] });
|
|
1321
|
+
}
|
|
1322
|
+
const segments = [];
|
|
1323
|
+
let sealed = false;
|
|
1324
|
+
const pushFlow = (list) => {
|
|
1325
|
+
if (!list.length) return;
|
|
1326
|
+
const last = segments[segments.length - 1];
|
|
1327
|
+
if (last && last.kind === "flow" && !sealed) last.items.push(...list);
|
|
1328
|
+
else segments.push({ kind: "flow", items: list });
|
|
1329
|
+
sealed = false;
|
|
1330
|
+
};
|
|
1331
|
+
let multiColumn = false;
|
|
1332
|
+
const isShortSpan = (f) => !f.table && isNarrow(f) && f.words <= 8;
|
|
1333
|
+
for (const band of bands) {
|
|
1334
|
+
const last = segments[segments.length - 1];
|
|
1335
|
+
if (band.spanning) {
|
|
1336
|
+
const lead = band.items[0];
|
|
1337
|
+
if (last && last.kind === "grid" && isShortSpan(lead) && minOf(last.items, (f) => f.bottom) - lead.top <= lead.size * 2) {
|
|
1338
|
+
last.items.push(lead);
|
|
1339
|
+
pushFlow(band.items.slice(1));
|
|
1340
|
+
} else pushFlow(band.items);
|
|
1341
|
+
continue;
|
|
1342
|
+
}
|
|
1343
|
+
const columns = Array.from({ length: gutters.length + 1 }, () => []);
|
|
1344
|
+
band.items.forEach((f) => columns[columnOf(f)].push(f));
|
|
1345
|
+
const used = columns.filter((c) => c.length);
|
|
1346
|
+
if (used.length < 2) {
|
|
1347
|
+
pushFlow(band.items);
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
const prose = used.every((col) => {
|
|
1351
|
+
const text = col.filter((f) => !f.table);
|
|
1352
|
+
if (text.length < 2) return text.length === 0;
|
|
1353
|
+
const colLeft = minOf(text, (f) => f.x0);
|
|
1354
|
+
const colRight = maxOf(text, (f) => f.x1);
|
|
1355
|
+
const fill = text.reduce((sum, f) => sum + (f.x1 - f.x0), 0) / text.length / Math.max(1, colRight - colLeft);
|
|
1356
|
+
const words = text.reduce((sum, f) => sum + f.words, 0) / text.length;
|
|
1357
|
+
return fill >= 0.55 && words >= 3;
|
|
1358
|
+
});
|
|
1359
|
+
const tops = used.map((col) => [minOf(col, (f) => f.bottom), maxOf(col, (f) => f.top)]);
|
|
1360
|
+
const overlapping = tops.every(([b, t], i) => i === 0 || Math.min(t, tops[0][1]) - Math.max(b, tops[0][0]) > 0);
|
|
1361
|
+
if (prose && overlapping) {
|
|
1362
|
+
multiColumn = true;
|
|
1363
|
+
for (const col of used) segments.push(...readingOrder(col, body, detectColumns, depth + 1, columnPages));
|
|
1364
|
+
sealed = true;
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
const pulled = [];
|
|
1368
|
+
if (last && last.kind === "flow" && !sealed) {
|
|
1369
|
+
const tail = last.items[last.items.length - 1];
|
|
1370
|
+
if (isShortSpan(tail) && tail.bottom - maxOf(band.items, (f) => f.top) <= tail.size * 2) {
|
|
1371
|
+
pulled.push(last.items.pop());
|
|
1372
|
+
if (!last.items.length) segments.pop();
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
const prevSegment = segments[segments.length - 1];
|
|
1376
|
+
if (prevSegment && prevSegment.kind === "grid" && (pulled.length || prevSegment === last)) {
|
|
1377
|
+
prevSegment.items.push(...pulled, ...band.items);
|
|
1378
|
+
} else segments.push({ kind: "grid", items: [...pulled, ...band.items] });
|
|
1379
|
+
sealed = false;
|
|
1380
|
+
}
|
|
1381
|
+
if (multiColumn && depth === 0) columnPages.count++;
|
|
1382
|
+
return segments;
|
|
1383
|
+
}
|
|
1384
|
+
function flowLines(items, page) {
|
|
1385
|
+
const lines = [];
|
|
1386
|
+
const sorted = [...items].sort((a, b) => b.top - a.top || a.x0 - b.x0);
|
|
1387
|
+
for (const f of sorted) {
|
|
1388
|
+
if (f.table) {
|
|
1389
|
+
lines.push({ text: "", x0: f.x0, x1: f.x1, y: f.y, top: f.top, size: f.size, bold: false, page, table: f.table });
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
const last = lines[lines.length - 1];
|
|
1393
|
+
if (last && !last.table && Math.abs(last.y - f.y) <= Math.min(last.size, f.size) * 0.5) {
|
|
1394
|
+
last.text = `${last.text} ${f.text}`;
|
|
1395
|
+
last.x0 = Math.min(last.x0, f.x0);
|
|
1396
|
+
last.x1 = Math.max(last.x1, f.x1);
|
|
1397
|
+
} else {
|
|
1398
|
+
lines.push({ text: f.text, x0: f.x0, x1: f.x1, y: f.y, top: f.top, size: f.size, bold: f.bold, page });
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
return lines;
|
|
1402
|
+
}
|
|
1403
|
+
function joinLines(prev, next, dehyphenate, stats) {
|
|
1404
|
+
if (prev.endsWith("\xAD")) {
|
|
1405
|
+
stats.dehyphenated++;
|
|
1406
|
+
return prev.slice(0, -1) + next;
|
|
1407
|
+
}
|
|
1408
|
+
if (dehyphenate && /[A-Za-zÀ-ɏ]-$/.test(prev) && /^[a-zß-ɏ]/.test(next)) {
|
|
1409
|
+
stats.dehyphenated++;
|
|
1410
|
+
return prev.slice(0, -1) + next;
|
|
1411
|
+
}
|
|
1412
|
+
return `${prev} ${next}`;
|
|
1413
|
+
}
|
|
1414
|
+
function listMarker(text) {
|
|
1415
|
+
const glyph = BULLET_GLYPH_RE.exec(text);
|
|
1416
|
+
if (glyph) return { kind: "glyph", rest: text.slice(glyph[0].length), ordered: false };
|
|
1417
|
+
const dash = BULLET_DASH_RE.exec(text);
|
|
1418
|
+
if (dash) return { kind: "dash", rest: text.slice(dash[0].length), ordered: false };
|
|
1419
|
+
const ordered = ORDERED_RE.exec(text);
|
|
1420
|
+
if (ordered) {
|
|
1421
|
+
const token = ordered[1] ?? ordered[2];
|
|
1422
|
+
const kind = /^\d+$/.test(token) ? "num" : /^[ivxlc]{2,}$/i.test(token) || /^i$/i.test(token) ? "roman" : "alpha";
|
|
1423
|
+
return { kind, rest: text.slice(ordered[0].length), ordered: true, value: kind === "num" ? Number(token) : void 0 };
|
|
1424
|
+
}
|
|
1425
|
+
return null;
|
|
1426
|
+
}
|
|
1427
|
+
function headingStyle(line, next, segRight, ctx) {
|
|
1428
|
+
if (!ctx.options.detectHeadings || line.table) return null;
|
|
1429
|
+
const text = line.text;
|
|
1430
|
+
const words = countWords(text);
|
|
1431
|
+
if (text.length > 200 || words > 25 || !/\p{L}/u.test(text)) return null;
|
|
1432
|
+
if (words > 15 && SENTENCE_END_RE.test(text)) return null;
|
|
1433
|
+
const ratio = line.size / ctx.body;
|
|
1434
|
+
if (ratio >= 1.15) {
|
|
1435
|
+
const confidence = Math.min(0.95, 0.6 + (ratio - 1.15) * 0.8 + (line.bold ? 0.1 : 0));
|
|
1436
|
+
return { key: Math.round(line.size * 2) / 2 + (line.bold ? 0.25 : 0), confidence, boldOnly: false };
|
|
1437
|
+
}
|
|
1438
|
+
const runsOn = !!next && !next.table && next.bold && Math.abs(next.size - line.size) < 0.5 && line.x1 >= segRight - 2 * line.size;
|
|
1439
|
+
if (line.bold && !ctx.boldBody && !runsOn && ratio >= 0.95 && text.length <= 100 && !/[.,;]$/.test(text)) {
|
|
1440
|
+
return { key: Math.round(line.size * 2) / 2 + 0.25, confidence: 0.6, boldOnly: true };
|
|
1441
|
+
}
|
|
1442
|
+
return null;
|
|
1443
|
+
}
|
|
1444
|
+
function buildBlocks(lines, ctx) {
|
|
1445
|
+
const textLines = lines.filter((l) => !l.table);
|
|
1446
|
+
const segLeft = textLines.length ? minOf(textLines, (l) => l.x0) : 0;
|
|
1447
|
+
const segRight = textLines.length ? maxOf(textLines, (l) => l.x1) : 0;
|
|
1448
|
+
const kindCounts = /* @__PURE__ */ new Map();
|
|
1449
|
+
const markers = lines.map((line) => {
|
|
1450
|
+
if (!ctx.options.detectLists || line.table) return null;
|
|
1451
|
+
const marker = listMarker(line.text);
|
|
1452
|
+
if (marker) kindCounts.set(marker.kind, (kindCounts.get(marker.kind) ?? 0) + 1);
|
|
1453
|
+
return marker;
|
|
1454
|
+
});
|
|
1455
|
+
let list = null;
|
|
1456
|
+
let listStack = [];
|
|
1457
|
+
let lastItemLine = null;
|
|
1458
|
+
let para = null;
|
|
1459
|
+
let heading = null;
|
|
1460
|
+
const closeAll = () => {
|
|
1461
|
+
if (para) {
|
|
1462
|
+
const last = para.lines[para.lines.length - 1];
|
|
1463
|
+
const ended = SENTENCE_END_RE.test(last.text) || last.x1 < segRight - 3 * last.size;
|
|
1464
|
+
ctx.open = ended ? null : { block: para.block, size: last.size, lastText: para.block.text };
|
|
1465
|
+
} else ctx.open = null;
|
|
1466
|
+
para = null;
|
|
1467
|
+
list = null;
|
|
1468
|
+
listStack = [];
|
|
1469
|
+
lastItemLine = null;
|
|
1470
|
+
heading = null;
|
|
1471
|
+
};
|
|
1472
|
+
lines.forEach((line, index) => {
|
|
1473
|
+
const prev = index > 0 ? lines[index - 1] : null;
|
|
1474
|
+
if (line.table) {
|
|
1475
|
+
closeAll();
|
|
1476
|
+
ctx.open = null;
|
|
1477
|
+
ctx.blocks.push(line.table);
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
const style = headingStyle(line, lines[index + 1], segRight, ctx);
|
|
1481
|
+
if (style) {
|
|
1482
|
+
if (heading && heading.key === style.key && heading.lines < 3 && prev === heading.line && prev.y - line.y <= line.size * 1.6) {
|
|
1483
|
+
heading.block.text = joinLines(heading.block.text, line.text, ctx.options.dehyphenate, ctx.stats);
|
|
1484
|
+
heading.line = line;
|
|
1485
|
+
heading.lines++;
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
closeAll();
|
|
1489
|
+
ctx.open = null;
|
|
1490
|
+
const block2 = { type: "heading", level: 1, text: line.text, page: line.page, confidence: style.confidence };
|
|
1491
|
+
ctx.blocks.push(block2);
|
|
1492
|
+
ctx.headings.push({ block: block2, key: style.key, boldOnly: style.boldOnly });
|
|
1493
|
+
heading = { block: block2, line, key: style.key, lines: 1 };
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
heading = null;
|
|
1497
|
+
const marker = markers[index];
|
|
1498
|
+
const validMarker = marker && (marker.kind === "glyph" || (kindCounts.get(marker.kind) ?? 0) >= 2) && marker.rest.trim() !== "";
|
|
1499
|
+
if (validMarker) {
|
|
1500
|
+
const gapOk = lastItemLine && lastItemLine.y - line.y <= Math.max(ctx.pitch(line.size) * 2.2, line.size * 2.4);
|
|
1501
|
+
if (!list || !gapOk) {
|
|
1502
|
+
closeAll();
|
|
1503
|
+
ctx.open = null;
|
|
1504
|
+
list = { type: "list", page: line.page, confidence: 0.6, items: [] };
|
|
1505
|
+
ctx.blocks.push(list);
|
|
1506
|
+
listStack = [line.x0];
|
|
1507
|
+
}
|
|
1508
|
+
const tol = line.size * 0.5;
|
|
1509
|
+
while (listStack.length > 1 && line.x0 < listStack[listStack.length - 1] - tol) listStack.pop();
|
|
1510
|
+
if (line.x0 > listStack[listStack.length - 1] + tol) listStack.push(line.x0);
|
|
1511
|
+
else listStack[listStack.length - 1] = Math.min(listStack[listStack.length - 1], line.x0);
|
|
1512
|
+
const prevDepth = list.items.length ? list.items[list.items.length - 1].depth : -1;
|
|
1513
|
+
const depth = Math.min(listStack.length - 1, prevDepth + 1);
|
|
1514
|
+
const item = {
|
|
1515
|
+
text: collapse(marker.rest),
|
|
1516
|
+
depth,
|
|
1517
|
+
ordered: marker.ordered
|
|
1518
|
+
};
|
|
1519
|
+
if (marker.value !== void 0) item.start = marker.value;
|
|
1520
|
+
list.items.push(item);
|
|
1521
|
+
list.confidence = Math.min(0.95, (marker.kind === "glyph" ? 0.75 : 0.6) + 0.05 * list.items.length);
|
|
1522
|
+
lastItemLine = line;
|
|
1523
|
+
para = null;
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
if (list && lastItemLine && prev) {
|
|
1527
|
+
const markerX = listStack[listStack.length - 1];
|
|
1528
|
+
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;
|
|
1529
|
+
if (continues) {
|
|
1530
|
+
const item = list.items[list.items.length - 1];
|
|
1531
|
+
item.text = joinLines(item.text, line.text, ctx.options.dehyphenate, ctx.stats);
|
|
1532
|
+
lastItemLine = line;
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
closeAll();
|
|
1536
|
+
}
|
|
1537
|
+
if (!para && ctx.open && index === 0 && /^[a-z]/.test(line.text) && Math.abs(ctx.open.size - line.size) <= line.size * 0.12) {
|
|
1538
|
+
ctx.open.block.text = joinLines(ctx.open.block.text, line.text, ctx.options.dehyphenate, ctx.stats);
|
|
1539
|
+
para = { block: ctx.open.block, lines: [line] };
|
|
1540
|
+
ctx.open = null;
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
if (para && prev && !prev.table) {
|
|
1544
|
+
const last = para.lines[para.lines.length - 1];
|
|
1545
|
+
const gap = last.y - line.y;
|
|
1546
|
+
const sameSize = Math.abs(last.size - line.size) <= last.size * 0.12;
|
|
1547
|
+
const closeEnough = gap > 0 && gap <= ctx.pitch(line.size) * ctx.options.paragraphGap;
|
|
1548
|
+
const indentEm = line.size * 0.8;
|
|
1549
|
+
const indented = line.x0 - segLeft >= indentEm && last.x0 - segLeft < indentEm && line.x0 - segLeft < line.size * 8;
|
|
1550
|
+
const shortEnded = last.x1 < segRight - 3 * last.size && SENTENCE_END_RE.test(last.text);
|
|
1551
|
+
if (sameSize && closeEnough && !indented && !shortEnded) {
|
|
1552
|
+
para.block.text = joinLines(para.block.text, line.text, ctx.options.dehyphenate, ctx.stats);
|
|
1553
|
+
para.lines.push(line);
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
closeAll();
|
|
1558
|
+
ctx.open = null;
|
|
1559
|
+
const block = { type: "paragraph", text: line.text, page: line.page };
|
|
1560
|
+
ctx.blocks.push(block);
|
|
1561
|
+
para = { block, lines: [line] };
|
|
1562
|
+
});
|
|
1563
|
+
closeAll();
|
|
1564
|
+
}
|
|
1565
|
+
function assignHeadingLevels(headings) {
|
|
1566
|
+
const keys = Array.from(new Set(headings.map((h) => h.key))).sort((a, b) => b - a);
|
|
1567
|
+
const levelOf = new Map(keys.map((key, i) => [key, Math.min(6, i + 1)]));
|
|
1568
|
+
headings.forEach((h) => {
|
|
1569
|
+
h.block.level = levelOf.get(h.key);
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
var DEFAULTS = {
|
|
1573
|
+
paragraphGap: 1.4,
|
|
1574
|
+
removeHeadersAndFooters: true,
|
|
1575
|
+
detectColumns: true,
|
|
1576
|
+
detectHeadings: true,
|
|
1577
|
+
detectLists: true,
|
|
1578
|
+
detectTables: true,
|
|
1579
|
+
dehyphenate: true
|
|
1580
|
+
};
|
|
1581
|
+
function analyzePdfLayout(pages, options = {}) {
|
|
1582
|
+
const opts = { ...DEFAULTS };
|
|
1583
|
+
Object.keys(options).forEach((key) => {
|
|
1584
|
+
if (options[key] !== void 0) opts[key] = options[key];
|
|
1585
|
+
});
|
|
1586
|
+
const fragPages = pages.map((page) => buildFragments(page.runs ?? []));
|
|
1587
|
+
const removed = opts.removeHeadersAndFooters ? removeHeadersAndFooters(fragPages) : { headers: 0, footers: 0, pageNumbers: 0 };
|
|
1588
|
+
const bySize = /* @__PURE__ */ new Map();
|
|
1589
|
+
let boldChars = 0;
|
|
1590
|
+
let totalChars = 0;
|
|
1591
|
+
fragPages.flat().forEach((f) => {
|
|
1592
|
+
const key = Math.round(f.size * 2) / 2;
|
|
1593
|
+
bySize.set(key, (bySize.get(key) ?? 0) + f.text.length);
|
|
1594
|
+
});
|
|
1595
|
+
let body = 10;
|
|
1596
|
+
let bodyChars = -1;
|
|
1597
|
+
bySize.forEach((chars, size) => {
|
|
1598
|
+
if (chars > bodyChars) {
|
|
1599
|
+
body = size;
|
|
1600
|
+
bodyChars = chars;
|
|
1601
|
+
}
|
|
1602
|
+
});
|
|
1603
|
+
fragPages.flat().forEach((f) => {
|
|
1604
|
+
if (Math.abs(f.size - body) <= body * 0.05) {
|
|
1605
|
+
totalChars += f.text.length;
|
|
1606
|
+
if (f.bold) boldChars += f.text.length;
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1609
|
+
const pitches = /* @__PURE__ */ new Map();
|
|
1610
|
+
fragPages.forEach((frags) => {
|
|
1611
|
+
const rows = baselineRows([...frags].sort((a, b) => b.y - a.y || a.x0 - b.x0));
|
|
1612
|
+
for (let k = 1; k < rows.length; k++) {
|
|
1613
|
+
const a = rows[k - 1][0];
|
|
1614
|
+
const b = rows[k][0];
|
|
1615
|
+
if (Math.abs(a.size - b.size) > 0.5) continue;
|
|
1616
|
+
const d = a.y - b.y;
|
|
1617
|
+
if (d > 0 && d < a.size * 3) {
|
|
1618
|
+
const key = Math.round(b.size * 2) / 2;
|
|
1619
|
+
if (!pitches.has(key)) pitches.set(key, []);
|
|
1620
|
+
pitches.get(key).push(d);
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
});
|
|
1624
|
+
const pitchMedians = /* @__PURE__ */ new Map();
|
|
1625
|
+
pitches.forEach((values, key) => pitchMedians.set(key, median(values)));
|
|
1626
|
+
const stats = { dehyphenated: 0 };
|
|
1627
|
+
const ctx = {
|
|
1628
|
+
body,
|
|
1629
|
+
boldBody: totalChars > 0 && boldChars / totalChars > 0.5,
|
|
1630
|
+
pitch: (size) => {
|
|
1631
|
+
const known = pitchMedians.get(Math.round(size * 2) / 2);
|
|
1632
|
+
return known && known >= size * 0.9 ? known : size * 1.2;
|
|
1633
|
+
},
|
|
1634
|
+
options: opts,
|
|
1635
|
+
stats,
|
|
1636
|
+
blocks: [],
|
|
1637
|
+
headings: [],
|
|
1638
|
+
open: null
|
|
1639
|
+
};
|
|
1640
|
+
const columnPages = { count: 0 };
|
|
1641
|
+
const items = [];
|
|
1642
|
+
fragPages.forEach((frags, pageIndex) => {
|
|
1643
|
+
const page = pageIndex + 1;
|
|
1644
|
+
let flowFrags = frags;
|
|
1645
|
+
const atoms = [];
|
|
1646
|
+
if (opts.detectTables && pages[pageIndex].rules?.length) {
|
|
1647
|
+
const ruled = ruledTables(frags, pages[pageIndex].rules, page, opts.dehyphenate, stats);
|
|
1648
|
+
flowFrags = frags.filter((f) => !ruled.consumed.has(f));
|
|
1649
|
+
atoms.push(...ruled.atoms);
|
|
1650
|
+
}
|
|
1651
|
+
const before = columnPages.count;
|
|
1652
|
+
const segments = readingOrder([...flowFrags, ...atoms], body, opts.detectColumns, 0, columnPages);
|
|
1653
|
+
if (columnPages.count > before) items.push({ type: "columns", page, confidence: 0.8, detail: "multi-column layout" });
|
|
1654
|
+
const units = [];
|
|
1655
|
+
let carry = [];
|
|
1656
|
+
for (const segment of segments) {
|
|
1657
|
+
if (segment.kind === "grid" && opts.detectTables) {
|
|
1658
|
+
const result = alignedTable(segment.items.filter((f) => !f.table), page, 3, opts.dehyphenate, stats);
|
|
1659
|
+
if (result) {
|
|
1660
|
+
const last = units[units.length - 1];
|
|
1661
|
+
if (result.before.length && last && last.kind === "flow") last.items.push(...carry, ...result.before);
|
|
1662
|
+
else if (result.before.length || carry.length) units.push({ kind: "flow", items: [...carry, ...result.before] });
|
|
1663
|
+
units.push({ kind: "table", table: result.table });
|
|
1664
|
+
carry = [...segment.items.filter((f) => f.table), ...result.leftover];
|
|
1665
|
+
continue;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
units.push({ kind: "flow", items: [...carry, ...segment.items] });
|
|
1669
|
+
carry = [];
|
|
1670
|
+
}
|
|
1671
|
+
if (carry.length) units.push({ kind: "flow", items: carry });
|
|
1672
|
+
for (const unit of units) {
|
|
1673
|
+
if (unit.kind === "table") {
|
|
1674
|
+
ctx.open = null;
|
|
1675
|
+
ctx.blocks.push(unit.table);
|
|
1676
|
+
} else buildBlocks(flowLines(unit.items, page), ctx);
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1679
|
+
assignHeadingLevels(ctx.headings);
|
|
1680
|
+
const counts = { headings: 0, lists: 0, tables: 0, paragraphs: 0 };
|
|
1681
|
+
const confidences = [];
|
|
1682
|
+
ctx.blocks.forEach((block) => {
|
|
1683
|
+
if (block.type === "heading") {
|
|
1684
|
+
counts.headings++;
|
|
1685
|
+
confidences.push(block.confidence);
|
|
1686
|
+
items.push({ type: "heading", page: block.page, confidence: block.confidence, detail: `H${block.level} "${truncate(block.text)}"` });
|
|
1687
|
+
} else if (block.type === "list") {
|
|
1688
|
+
counts.lists++;
|
|
1689
|
+
confidences.push(block.confidence);
|
|
1690
|
+
const depth = maxOf(block.items, (i) => i.depth) + 1;
|
|
1691
|
+
items.push({
|
|
1692
|
+
type: "list",
|
|
1693
|
+
page: block.page,
|
|
1694
|
+
confidence: block.confidence,
|
|
1695
|
+
detail: `${block.items[0]?.ordered ? "numbered" : "bulleted"} list, ${block.items.length} items${depth > 1 ? `, ${depth} levels` : ""}`
|
|
1696
|
+
});
|
|
1697
|
+
} else if (block.type === "table") {
|
|
1698
|
+
counts.tables++;
|
|
1699
|
+
confidences.push(block.confidence);
|
|
1700
|
+
items.push({
|
|
1701
|
+
type: "table",
|
|
1702
|
+
page: block.page,
|
|
1703
|
+
confidence: block.confidence,
|
|
1704
|
+
detail: `${block.rows.length}\xD7${block.columns} table${block.ruled ? " (ruled)" : ""}${block.headerRows ? ", header row" : ""}`
|
|
1705
|
+
});
|
|
1706
|
+
} else counts.paragraphs++;
|
|
1707
|
+
});
|
|
1708
|
+
items.sort((a, b) => a.page - b.page);
|
|
1709
|
+
return {
|
|
1710
|
+
blocks: ctx.blocks,
|
|
1711
|
+
report: {
|
|
1712
|
+
mode: "structured",
|
|
1713
|
+
pages: pages.length,
|
|
1714
|
+
counts,
|
|
1715
|
+
multiColumnPages: columnPages.count,
|
|
1716
|
+
confidence: confidences.length ? Math.round(confidences.reduce((a, b) => a + b, 0) / confidences.length * 100) / 100 : 1,
|
|
1717
|
+
items,
|
|
1718
|
+
removed,
|
|
1719
|
+
dehyphenated: stats.dehyphenated
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
var truncate = (text) => text.length > 60 ? `${text.slice(0, 57)}\u2026` : text;
|
|
1724
|
+
function listHtml(items) {
|
|
1725
|
+
let html = "";
|
|
1726
|
+
const stack = [];
|
|
1727
|
+
for (const item of items) {
|
|
1728
|
+
const level = item.depth + 1;
|
|
1729
|
+
while (stack.length > level) html += `</li></${stack.pop()}>`;
|
|
1730
|
+
const tag = item.ordered ? "ol" : "ul";
|
|
1731
|
+
if (stack.length === level) {
|
|
1732
|
+
if (stack[stack.length - 1] !== tag) {
|
|
1733
|
+
html += `</li></${stack.pop()}>`;
|
|
1734
|
+
} else html += "</li>";
|
|
1735
|
+
}
|
|
1736
|
+
while (stack.length < level) {
|
|
1737
|
+
const start = item.ordered && item.start !== void 0 && item.start !== 1 ? ` start="${item.start}"` : "";
|
|
1738
|
+
html += `<${tag}${start}>`;
|
|
1739
|
+
stack.push(tag);
|
|
1740
|
+
}
|
|
1741
|
+
html += `<li><p>${escapeHtml(item.text)}</p>`;
|
|
1742
|
+
}
|
|
1743
|
+
while (stack.length) html += `</li></${stack.pop()}>`;
|
|
1744
|
+
return html;
|
|
1745
|
+
}
|
|
1746
|
+
function pdfLayoutBlocksToHtml(blocks) {
|
|
1747
|
+
let html = "";
|
|
1748
|
+
for (const block of blocks) {
|
|
1749
|
+
if (block.type === "heading") html += `<h${block.level}>${escapeHtml(block.text)}</h${block.level}>`;
|
|
1750
|
+
else if (block.type === "paragraph") html += `<p>${escapeHtml(block.text)}</p>`;
|
|
1751
|
+
else if (block.type === "list") html += listHtml(block.items);
|
|
1752
|
+
else {
|
|
1753
|
+
html += "<table><tbody>";
|
|
1754
|
+
for (const row of block.rows) {
|
|
1755
|
+
html += "<tr>";
|
|
1756
|
+
for (const cell of row) {
|
|
1757
|
+
const tag = cell.header ? "th" : "td";
|
|
1758
|
+
const attrs = `${cell.colSpan > 1 ? ` colspan="${cell.colSpan}"` : ""}${cell.rowSpan > 1 ? ` rowspan="${cell.rowSpan}"` : ""}`;
|
|
1759
|
+
html += `<${tag}${attrs}><p>${escapeHtml(cell.text)}</p></${tag}>`;
|
|
1760
|
+
}
|
|
1761
|
+
html += "</tr>";
|
|
1762
|
+
}
|
|
1763
|
+
html += "</tbody></table>";
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
return html || "<p></p>";
|
|
1767
|
+
}
|
|
603
1768
|
|
|
604
1769
|
// src/import/pdf.ts
|
|
605
1770
|
var isTextItem = (item) => typeof item.str === "string";
|
|
606
|
-
function
|
|
1771
|
+
function median2(values) {
|
|
607
1772
|
if (!values.length) return 0;
|
|
608
1773
|
const sorted = [...values].sort((a, b) => a - b);
|
|
609
1774
|
const mid = sorted.length >> 1;
|
|
@@ -646,7 +1811,7 @@ function pdfTextItemsToParagraphs(items, options = {}) {
|
|
|
646
1811
|
const gap = lines[i - 1].y - lines[i].y;
|
|
647
1812
|
if (gap > 0) gaps.push(gap);
|
|
648
1813
|
}
|
|
649
|
-
const typical =
|
|
1814
|
+
const typical = median2(gaps);
|
|
650
1815
|
const factor = options.paragraphGap ?? 1.4;
|
|
651
1816
|
const paragraphs = [];
|
|
652
1817
|
let current = [];
|
|
@@ -673,6 +1838,228 @@ function pdfTextItemsToParagraphs(items, options = {}) {
|
|
|
673
1838
|
flush();
|
|
674
1839
|
return paragraphs;
|
|
675
1840
|
}
|
|
1841
|
+
function pdfTextItemsToRuns(items, font) {
|
|
1842
|
+
const runs = [];
|
|
1843
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1844
|
+
for (const item of items) {
|
|
1845
|
+
if (!isTextItem(item) || !item.str.trim()) continue;
|
|
1846
|
+
const t = item.transform ?? [];
|
|
1847
|
+
const fontSize = Math.hypot(t[2] ?? 0, t[3] ?? 0) || item.height || 10;
|
|
1848
|
+
let info;
|
|
1849
|
+
if (item.fontName && font) {
|
|
1850
|
+
if (!cache.has(item.fontName)) cache.set(item.fontName, font(item.fontName));
|
|
1851
|
+
info = cache.get(item.fontName);
|
|
1852
|
+
}
|
|
1853
|
+
runs.push({
|
|
1854
|
+
text: item.str,
|
|
1855
|
+
x: t[4] ?? 0,
|
|
1856
|
+
y: t[5] ?? 0,
|
|
1857
|
+
width: item.width,
|
|
1858
|
+
fontSize,
|
|
1859
|
+
fontName: info?.name ?? item.fontName,
|
|
1860
|
+
bold: info?.bold,
|
|
1861
|
+
italic: info?.italic
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
return runs;
|
|
1865
|
+
}
|
|
1866
|
+
var DEFAULT_OPS = {
|
|
1867
|
+
save: 10,
|
|
1868
|
+
restore: 11,
|
|
1869
|
+
transform: 12,
|
|
1870
|
+
moveTo: 13,
|
|
1871
|
+
lineTo: 14,
|
|
1872
|
+
curveTo: 15,
|
|
1873
|
+
curveTo2: 16,
|
|
1874
|
+
curveTo3: 17,
|
|
1875
|
+
closePath: 18,
|
|
1876
|
+
rectangle: 19,
|
|
1877
|
+
stroke: 20,
|
|
1878
|
+
closeStroke: 21,
|
|
1879
|
+
fill: 22,
|
|
1880
|
+
eoFill: 23,
|
|
1881
|
+
fillStroke: 24,
|
|
1882
|
+
eoFillStroke: 25,
|
|
1883
|
+
closeFillStroke: 26,
|
|
1884
|
+
closeEOFillStroke: 27,
|
|
1885
|
+
endPath: 28,
|
|
1886
|
+
constructPath: 91
|
|
1887
|
+
};
|
|
1888
|
+
var DRAW_OPS = { moveTo: 0, lineTo: 1, curveTo: 2, quadraticCurveTo: 3, closePath: 4 };
|
|
1889
|
+
var MAX_PAGE_RULES = 5e3;
|
|
1890
|
+
var IDENTITY = [1, 0, 0, 1, 0, 0];
|
|
1891
|
+
var multiply = (m, c) => [
|
|
1892
|
+
m[0] * c[0] + m[1] * c[2],
|
|
1893
|
+
m[0] * c[1] + m[1] * c[3],
|
|
1894
|
+
m[2] * c[0] + m[3] * c[2],
|
|
1895
|
+
m[2] * c[1] + m[3] * c[3],
|
|
1896
|
+
m[4] * c[0] + m[5] * c[2] + c[4],
|
|
1897
|
+
m[4] * c[1] + m[5] * c[3] + c[5]
|
|
1898
|
+
];
|
|
1899
|
+
var apply = (m, x, y) => [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
1900
|
+
function pdfOperatorListToRules(list, opsTable) {
|
|
1901
|
+
const OPS = { ...DEFAULT_OPS, ...opsTable ?? {} };
|
|
1902
|
+
const stroking = /* @__PURE__ */ new Set([OPS.stroke, OPS.closeStroke, OPS.fillStroke, OPS.eoFillStroke, OPS.closeFillStroke, OPS.closeEOFillStroke]);
|
|
1903
|
+
const filling = /* @__PURE__ */ new Set([OPS.fill, OPS.eoFill, OPS.fillStroke, OPS.eoFillStroke, OPS.closeFillStroke, OPS.closeEOFillStroke]);
|
|
1904
|
+
const rules = [];
|
|
1905
|
+
const stack = [];
|
|
1906
|
+
let ctm = IDENTITY;
|
|
1907
|
+
let lines = [];
|
|
1908
|
+
let rects = [];
|
|
1909
|
+
const num = (value) => typeof value === "number" && Number.isFinite(value) ? value : NaN;
|
|
1910
|
+
const addLine = (x1, y1, x2, y2) => {
|
|
1911
|
+
const [a, b] = apply(ctm, x1, y1);
|
|
1912
|
+
const [c, d] = apply(ctm, x2, y2);
|
|
1913
|
+
lines.push([a, b, c, d]);
|
|
1914
|
+
};
|
|
1915
|
+
const addRect = (x, y, w, h) => {
|
|
1916
|
+
const corners = [apply(ctm, x, y), apply(ctm, x + w, y), apply(ctm, x + w, y + h), apply(ctm, x, y + h)];
|
|
1917
|
+
const xs = corners.map((p) => p[0]);
|
|
1918
|
+
const ys = corners.map((p) => p[1]);
|
|
1919
|
+
rects.push([Math.min(...xs), Math.min(...ys), Math.max(...xs), Math.max(...ys)]);
|
|
1920
|
+
};
|
|
1921
|
+
const paint = (op) => {
|
|
1922
|
+
const stroke = stroking.has(op);
|
|
1923
|
+
const fill = filling.has(op);
|
|
1924
|
+
if (stroke) {
|
|
1925
|
+
for (const [x1, y1, x2, y2] of lines) rules.push({ x1, y1, x2, y2 });
|
|
1926
|
+
for (const [x0, y0, x1, y1] of rects) {
|
|
1927
|
+
rules.push({ x1: x0, y1: y0, x2: x1, y2: y0 }, { x1: x0, y1, x2: x1, y2: y1 });
|
|
1928
|
+
rules.push({ x1: x0, y1: y0, x2: x0, y2: y1 }, { x1, y1: y0, x2: x1, y2: y1 });
|
|
1929
|
+
}
|
|
1930
|
+
} else if (fill) {
|
|
1931
|
+
for (const [x0, y0, x1, y1] of rects) {
|
|
1932
|
+
if (y1 - y0 <= 2 && x1 - x0 > 2) rules.push({ x1: x0, y1: (y0 + y1) / 2, x2: x1, y2: (y0 + y1) / 2 });
|
|
1933
|
+
else if (x1 - x0 <= 2 && y1 - y0 > 2) rules.push({ x1: (x0 + x1) / 2, y1: y0, x2: (x0 + x1) / 2, y2: y1 });
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
lines = [];
|
|
1937
|
+
rects = [];
|
|
1938
|
+
};
|
|
1939
|
+
const readPath = (subOps, subArgs) => {
|
|
1940
|
+
let k = 0;
|
|
1941
|
+
let cx = 0;
|
|
1942
|
+
let cy = 0;
|
|
1943
|
+
let sx = 0;
|
|
1944
|
+
let sy = 0;
|
|
1945
|
+
for (let i = 0; i < subOps.length; i++) {
|
|
1946
|
+
const op = subOps[i];
|
|
1947
|
+
if (op === OPS.moveTo) {
|
|
1948
|
+
cx = sx = num(subArgs[k++]);
|
|
1949
|
+
cy = sy = num(subArgs[k++]);
|
|
1950
|
+
} else if (op === OPS.lineTo) {
|
|
1951
|
+
const x = num(subArgs[k++]);
|
|
1952
|
+
const y = num(subArgs[k++]);
|
|
1953
|
+
addLine(cx, cy, x, y);
|
|
1954
|
+
cx = x;
|
|
1955
|
+
cy = y;
|
|
1956
|
+
} else if (op === OPS.rectangle) {
|
|
1957
|
+
addRect(num(subArgs[k++]), num(subArgs[k++]), num(subArgs[k++]), num(subArgs[k++]));
|
|
1958
|
+
} else if (op === OPS.curveTo) {
|
|
1959
|
+
k += 4;
|
|
1960
|
+
cx = num(subArgs[k++]);
|
|
1961
|
+
cy = num(subArgs[k++]);
|
|
1962
|
+
} else if (op === OPS.curveTo2 || op === OPS.curveTo3) {
|
|
1963
|
+
k += 2;
|
|
1964
|
+
cx = num(subArgs[k++]);
|
|
1965
|
+
cy = num(subArgs[k++]);
|
|
1966
|
+
} else if (op === OPS.closePath) {
|
|
1967
|
+
if (cx !== sx || cy !== sy) addLine(cx, cy, sx, sy);
|
|
1968
|
+
cx = sx;
|
|
1969
|
+
cy = sy;
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1973
|
+
const readDrawBuffer = (data) => {
|
|
1974
|
+
let cx = 0;
|
|
1975
|
+
let cy = 0;
|
|
1976
|
+
let sx = 0;
|
|
1977
|
+
let sy = 0;
|
|
1978
|
+
for (let k = 0; k < data.length; ) {
|
|
1979
|
+
const code = data[k++];
|
|
1980
|
+
if (code === DRAW_OPS.moveTo) {
|
|
1981
|
+
cx = sx = data[k++];
|
|
1982
|
+
cy = sy = data[k++];
|
|
1983
|
+
} else if (code === DRAW_OPS.lineTo) {
|
|
1984
|
+
const x = data[k++];
|
|
1985
|
+
const y = data[k++];
|
|
1986
|
+
addLine(cx, cy, x, y);
|
|
1987
|
+
cx = x;
|
|
1988
|
+
cy = y;
|
|
1989
|
+
} else if (code === DRAW_OPS.curveTo) {
|
|
1990
|
+
k += 4;
|
|
1991
|
+
cx = data[k++];
|
|
1992
|
+
cy = data[k++];
|
|
1993
|
+
} else if (code === DRAW_OPS.quadraticCurveTo) {
|
|
1994
|
+
k += 2;
|
|
1995
|
+
cx = data[k++];
|
|
1996
|
+
cy = data[k++];
|
|
1997
|
+
} else if (code === DRAW_OPS.closePath) {
|
|
1998
|
+
if (cx !== sx || cy !== sy) addLine(cx, cy, sx, sy);
|
|
1999
|
+
cx = sx;
|
|
2000
|
+
cy = sy;
|
|
2001
|
+
} else break;
|
|
2002
|
+
}
|
|
2003
|
+
};
|
|
2004
|
+
for (let i = 0; i < list.fnArray.length && rules.length < MAX_PAGE_RULES; i++) {
|
|
2005
|
+
const fn = list.fnArray[i];
|
|
2006
|
+
const args = list.argsArray[i];
|
|
2007
|
+
if (fn === OPS.save) stack.push(ctm);
|
|
2008
|
+
else if (fn === OPS.restore) ctm = stack.pop() ?? IDENTITY;
|
|
2009
|
+
else if (fn === OPS.transform && args && args.length >= 6) {
|
|
2010
|
+
const m = Array.from({ length: 6 }, (_, k) => num(args[k]));
|
|
2011
|
+
if (m.every(Number.isFinite)) ctm = multiply(m, ctm);
|
|
2012
|
+
} else if (fn === OPS.constructPath && args) {
|
|
2013
|
+
const first = args[0];
|
|
2014
|
+
if (typeof first === "number") {
|
|
2015
|
+
const buffers = args[1];
|
|
2016
|
+
const data = buffers?.[0];
|
|
2017
|
+
if (data && typeof data.length === "number") readDrawBuffer(data);
|
|
2018
|
+
paint(first);
|
|
2019
|
+
} else if (first && typeof first.length === "number") {
|
|
2020
|
+
readPath(first, args[1] ?? []);
|
|
2021
|
+
}
|
|
2022
|
+
} else if (stroking.has(fn) || filling.has(fn)) paint(fn);
|
|
2023
|
+
else if (fn === OPS.endPath) {
|
|
2024
|
+
lines = [];
|
|
2025
|
+
rects = [];
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
return rules.filter((rule) => [rule.x1, rule.y1, rule.x2, rule.y2].every(Number.isFinite));
|
|
2029
|
+
}
|
|
2030
|
+
function fontResolver(page, content) {
|
|
2031
|
+
return (fontName) => {
|
|
2032
|
+
let info;
|
|
2033
|
+
try {
|
|
2034
|
+
if (page.commonObjs && (!page.commonObjs.has || page.commonObjs.has(fontName))) {
|
|
2035
|
+
const font = page.commonObjs.get(fontName);
|
|
2036
|
+
if (font && typeof font === "object") {
|
|
2037
|
+
info = {
|
|
2038
|
+
name: typeof font.name === "string" ? font.name : void 0,
|
|
2039
|
+
bold: font.bold || font.black ? true : void 0,
|
|
2040
|
+
italic: font.italic ? true : void 0
|
|
2041
|
+
};
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
} catch {
|
|
2045
|
+
}
|
|
2046
|
+
const family = content.styles?.[fontName]?.fontFamily;
|
|
2047
|
+
if (!info?.name && family) info = { ...info, name: family };
|
|
2048
|
+
return info;
|
|
2049
|
+
};
|
|
2050
|
+
}
|
|
2051
|
+
function plainReport(paragraphs, pages) {
|
|
2052
|
+
return {
|
|
2053
|
+
mode: "plain",
|
|
2054
|
+
pages,
|
|
2055
|
+
counts: { headings: 0, lists: 0, tables: 0, paragraphs },
|
|
2056
|
+
multiColumnPages: 0,
|
|
2057
|
+
confidence: 1,
|
|
2058
|
+
items: [],
|
|
2059
|
+
removed: { headers: 0, footers: 0, pageNumbers: 0 },
|
|
2060
|
+
dehyphenated: 0
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
676
2063
|
function createPdfImportAdapter(pdfjs, options = {}) {
|
|
677
2064
|
return {
|
|
678
2065
|
id: options.id ?? "pdf",
|
|
@@ -681,22 +2068,47 @@ function createPdfImportAdapter(pdfjs, options = {}) {
|
|
|
681
2068
|
extensions: [".pdf"],
|
|
682
2069
|
target: "document",
|
|
683
2070
|
async import(_input, context) {
|
|
2071
|
+
const call = context.options && typeof context.options === "object" ? context.options : {};
|
|
2072
|
+
const opts = { ...options, ...call, layout: { ...options.layout, ...call.layout } };
|
|
2073
|
+
const structured = opts.structure !== false;
|
|
684
2074
|
const data = new Uint8Array((await context.readArrayBuffer()).slice(0));
|
|
685
|
-
const doc = await pdfjs.getDocument({ ...
|
|
2075
|
+
const doc = await pdfjs.getDocument({ ...opts.documentParams, data }).promise;
|
|
686
2076
|
const paragraphs = [];
|
|
2077
|
+
const layoutPages = [];
|
|
2078
|
+
let pages = 0;
|
|
687
2079
|
try {
|
|
688
|
-
|
|
2080
|
+
pages = Math.min(doc.numPages, opts.maxPages ?? Infinity);
|
|
689
2081
|
for (let n = 1; n <= pages; n++) {
|
|
690
2082
|
const page = await doc.getPage(n);
|
|
691
|
-
|
|
692
|
-
|
|
2083
|
+
if (!structured) {
|
|
2084
|
+
const content = await page.getTextContent();
|
|
2085
|
+
paragraphs.push(...pdfTextItemsToParagraphs(content.items, opts));
|
|
2086
|
+
} else {
|
|
2087
|
+
let rules = [];
|
|
2088
|
+
if (opts.rulingLines !== false && typeof page.getOperatorList === "function") {
|
|
2089
|
+
try {
|
|
2090
|
+
rules = pdfOperatorListToRules(await page.getOperatorList(), pdfjs.OPS);
|
|
2091
|
+
} catch {
|
|
2092
|
+
rules = [];
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
const content = await page.getTextContent();
|
|
2096
|
+
layoutPages.push({ runs: pdfTextItemsToRuns(content.items, fontResolver(page, content)), rules });
|
|
2097
|
+
}
|
|
693
2098
|
page.cleanup?.();
|
|
694
2099
|
}
|
|
695
2100
|
} finally {
|
|
696
2101
|
await doc.destroy?.();
|
|
697
2102
|
}
|
|
698
|
-
|
|
699
|
-
|
|
2103
|
+
if (!structured) {
|
|
2104
|
+
const text = paragraphs.join("\n");
|
|
2105
|
+
return { html: plainTextToParagraphHtml(text), text, structure: plainReport(paragraphs.length, pages) };
|
|
2106
|
+
}
|
|
2107
|
+
const layout = { ...opts.layout };
|
|
2108
|
+
if (layout.paragraphGap === void 0 && opts.paragraphGap !== void 0) layout.paragraphGap = opts.paragraphGap;
|
|
2109
|
+
const { blocks, report } = analyzePdfLayout(layoutPages, layout);
|
|
2110
|
+
const html = sanitizeImportedHtml(pdfLayoutBlocksToHtml(blocks));
|
|
2111
|
+
return { html, text: htmlToPlainText(html), structure: report };
|
|
700
2112
|
}
|
|
701
2113
|
};
|
|
702
2114
|
}
|
|
@@ -795,24 +2207,45 @@ export {
|
|
|
795
2207
|
BLOCK_CHANGE_ATTRIBUTE,
|
|
796
2208
|
BUILT_IN_IMPORT_ADAPTERS,
|
|
797
2209
|
Bookmark,
|
|
2210
|
+
CHARACTER_STYLE_MARK_NAME,
|
|
798
2211
|
COMMENT_MARK_NAME,
|
|
2212
|
+
CONDITIONAL_FORMAT_ICON_SETS,
|
|
2213
|
+
CONDITIONAL_FORMAT_PRESETS,
|
|
2214
|
+
CONDITIONAL_FORMAT_STYLE_PRESETS,
|
|
2215
|
+
CONDITIONAL_FORMAT_TIME_PERIODS,
|
|
2216
|
+
CharacterStyle,
|
|
799
2217
|
ColorHighlighter,
|
|
800
2218
|
CommentStore,
|
|
801
2219
|
Comments,
|
|
2220
|
+
ConditionalFormatEngine,
|
|
802
2221
|
CrossReference,
|
|
2222
|
+
DATA_VALIDATION_ERROR_STYLE_OPTIONS,
|
|
2223
|
+
DATA_VALIDATION_OPERATOR_OPTIONS,
|
|
2224
|
+
DATA_VALIDATION_TYPE_OPTIONS,
|
|
803
2225
|
DEFAULT_AUTOCORRECT_EXCEPTIONS,
|
|
804
2226
|
DEFAULT_COLUMN_WIDTH,
|
|
2227
|
+
DEFAULT_CONDITIONAL_FORMAT_STYLE,
|
|
2228
|
+
DEFAULT_DATA_VALIDATION_MESSAGE,
|
|
2229
|
+
DEFAULT_DATA_VALIDATION_TITLE,
|
|
805
2230
|
DEFAULT_DOCX_MAX_IMAGE_SIZE,
|
|
806
2231
|
DEFAULT_ROW_HEIGHT,
|
|
2232
|
+
DEFAULT_STYLES,
|
|
2233
|
+
DEFAULT_TABLE_OPTIONS,
|
|
2234
|
+
DEFAULT_TABLE_TOOLBAR,
|
|
807
2235
|
DEFAULT_ZIP_MAX_ENTRIES,
|
|
808
2236
|
DEFAULT_ZIP_MAX_TOTAL_SIZE,
|
|
809
2237
|
DELETION_MARK_NAME,
|
|
2238
|
+
DOCX_ANONYMOUS_AUTHOR,
|
|
2239
|
+
DOCX_EXPORT_MIME_TYPE,
|
|
810
2240
|
DOCX_MIME_TYPES,
|
|
811
2241
|
DataSourceBinder,
|
|
812
2242
|
DependencyGraph,
|
|
813
2243
|
DirtyTracker,
|
|
814
2244
|
DocumentCompare,
|
|
2245
|
+
DocxExportController,
|
|
2246
|
+
EMPTY_CONDITIONAL_FORMAT_OVERLAY,
|
|
815
2247
|
EMPTY_FIND_REPLACE_SNAPSHOT,
|
|
2248
|
+
EMPTY_TABLE_STATE,
|
|
816
2249
|
EditorController,
|
|
817
2250
|
FIELD_ALIASES,
|
|
818
2251
|
FIND_OPTION_TOGGLES,
|
|
@@ -828,6 +2261,7 @@ export {
|
|
|
828
2261
|
FootnoteReference,
|
|
829
2262
|
Footnotes,
|
|
830
2263
|
FormulaEvaluator,
|
|
2264
|
+
FormulaLambda,
|
|
831
2265
|
FormulaParser,
|
|
832
2266
|
GradientText,
|
|
833
2267
|
HistoryManager,
|
|
@@ -836,35 +2270,59 @@ export {
|
|
|
836
2270
|
Image,
|
|
837
2271
|
ImportAdapterRegistry,
|
|
838
2272
|
ImportError,
|
|
2273
|
+
IntervalIndex,
|
|
839
2274
|
LoadingNode,
|
|
840
2275
|
MARKDOWN_MENTION_SPLIT_REGEX,
|
|
841
2276
|
MAX_DATA_SOURCE_FIELDS,
|
|
842
2277
|
MAX_DATA_SOURCE_RECORDS,
|
|
2278
|
+
MAX_DEFINED_NAME_LENGTH,
|
|
843
2279
|
MAX_FIND_PATTERN_LENGTH,
|
|
844
2280
|
MAX_FORMULA_ARRAY_SIZE,
|
|
2281
|
+
MAX_LAMBDA_DEPTH,
|
|
845
2282
|
MAX_MERGE_LENGTH,
|
|
846
2283
|
MAX_MERGE_OUTPUTS,
|
|
847
2284
|
MAX_NUMBER_FORMAT_CODE_CHARS,
|
|
2285
|
+
MAX_SHEET_NAME_LENGTH,
|
|
2286
|
+
MAX_TABLE_COLUMNS,
|
|
2287
|
+
MAX_TABLE_ROWS,
|
|
848
2288
|
MENTION_REGEX,
|
|
2289
|
+
MOVE_FROM_CLASS,
|
|
2290
|
+
MOVE_ID_ATTRIBUTE,
|
|
2291
|
+
MOVE_TO_CLASS,
|
|
849
2292
|
Markdown,
|
|
850
2293
|
Mention,
|
|
2294
|
+
NORMAL_STYLE_ID,
|
|
851
2295
|
NUMBER_FORMAT_PRESETS,
|
|
852
2296
|
NumberFormat,
|
|
853
2297
|
Outline,
|
|
854
2298
|
PIXERATE_DOCUMENT_MIME,
|
|
2299
|
+
ParagraphStyles,
|
|
855
2300
|
RichClipboard,
|
|
856
2301
|
SMILIE_REPLACEMENTS,
|
|
857
2302
|
SPREADSHEET_CLIPBOARD_MIME,
|
|
2303
|
+
SPREADSHEET_COLUMN_HEADER_HEIGHT,
|
|
2304
|
+
SPREADSHEET_DEFAULT_VIEWPORT,
|
|
2305
|
+
SPREADSHEET_GROUP_ROW_HEIGHT,
|
|
858
2306
|
SPREADSHEET_IMPORT_ADAPTERS,
|
|
2307
|
+
SPREADSHEET_ROW_HEADER_WIDTH,
|
|
859
2308
|
SPREADSHEET_TABLE_ACTIONS,
|
|
2309
|
+
SPREADSHEET_VIRTUAL_COLUMN_THRESHOLD,
|
|
2310
|
+
SPREADSHEET_VIRTUAL_ROW_THRESHOLD,
|
|
2311
|
+
STYLE_ID_ATTRIBUTE,
|
|
860
2312
|
SlashCommands,
|
|
861
2313
|
SmilieReplacer,
|
|
862
2314
|
SpreadsheetController,
|
|
2315
|
+
StyleRegistry,
|
|
2316
|
+
TABLE_ACTIONS,
|
|
863
2317
|
TEMPLATE_DEPTH_ERROR,
|
|
864
2318
|
TEMPLATE_LOOP_ERROR,
|
|
865
2319
|
TEMPLATE_REGEX,
|
|
866
2320
|
TRACK_CHANGES_SKIP_META,
|
|
2321
|
+
Table,
|
|
2322
|
+
TableCell,
|
|
2323
|
+
TableHeader,
|
|
867
2324
|
TableOfContents,
|
|
2325
|
+
TableRow,
|
|
868
2326
|
TemplateSuggestions,
|
|
869
2327
|
TrackChanges,
|
|
870
2328
|
TrackChangesStore,
|
|
@@ -873,20 +2331,27 @@ export {
|
|
|
873
2331
|
TrackedInsertion,
|
|
874
2332
|
VARIABLE_REGEX,
|
|
875
2333
|
WHOLE_COLUMN_END_ROW,
|
|
2334
|
+
XmlWriter,
|
|
876
2335
|
ZipArchive,
|
|
877
2336
|
ZipError,
|
|
2337
|
+
adjustRangeForStructuralChange,
|
|
2338
|
+
adjustRangesForStructuralChange,
|
|
878
2339
|
aggregateValues,
|
|
2340
|
+
analyzePdfLayout,
|
|
879
2341
|
applyDocumentComparison,
|
|
880
2342
|
applyFormulaSuggestion,
|
|
2343
|
+
applyImportedReviewData,
|
|
881
2344
|
applyReplacements,
|
|
882
2345
|
autocorrectPluginKey,
|
|
883
2346
|
bindDirtyToHistory,
|
|
884
2347
|
bindSpreadsheetTableActions,
|
|
2348
|
+
blendConditionalFormatColors,
|
|
885
2349
|
buildOutlineTree,
|
|
886
2350
|
buildSpreadsheetView,
|
|
887
2351
|
builtinNumberFormat,
|
|
888
2352
|
builtinNumberFormatId,
|
|
889
2353
|
capitalizeSentenceRules,
|
|
2354
|
+
captureSelectionFormat,
|
|
890
2355
|
cellFormatForNumberFormat,
|
|
891
2356
|
checkFormulaArgumentCount,
|
|
892
2357
|
clampMenuPosition,
|
|
@@ -907,9 +2372,17 @@ export {
|
|
|
907
2372
|
computeOutline,
|
|
908
2373
|
computeRowGroups,
|
|
909
2374
|
conditionSubject,
|
|
2375
|
+
conditionalFormatContrastColor,
|
|
2376
|
+
conditionalFormatIconCount,
|
|
2377
|
+
conditionalFormatNumber,
|
|
2378
|
+
conditionalFormatStyleString,
|
|
2379
|
+
copySheetName,
|
|
910
2380
|
createCommentStore,
|
|
2381
|
+
createConditionalFormatRule,
|
|
911
2382
|
createDirtyTracker,
|
|
2383
|
+
createDocxExportController,
|
|
912
2384
|
createDocxImportAdapter,
|
|
2385
|
+
createDocxParts,
|
|
913
2386
|
createEditor,
|
|
914
2387
|
createFileImportController,
|
|
915
2388
|
createFindReplaceCommands,
|
|
@@ -918,39 +2391,58 @@ export {
|
|
|
918
2391
|
createImportContext,
|
|
919
2392
|
createMentionExtension,
|
|
920
2393
|
createOutlineStore,
|
|
2394
|
+
createParagraphStylesStore,
|
|
921
2395
|
createPdfImportAdapter,
|
|
922
2396
|
createReviewId,
|
|
923
2397
|
createRichTextPreset,
|
|
924
2398
|
createSearchBudget,
|
|
925
2399
|
createSpreadsheetClipboardData,
|
|
2400
|
+
createStyleRegistry,
|
|
2401
|
+
createTableCommands,
|
|
2402
|
+
createTableExtensions,
|
|
2403
|
+
createTableStore,
|
|
926
2404
|
createZipImportAdapter,
|
|
927
2405
|
crossReferencePluginKey,
|
|
928
2406
|
csvImportAdapter,
|
|
929
2407
|
dateValueToSerial,
|
|
930
2408
|
defaultAutocorrectRules,
|
|
2409
|
+
defaultIconThresholds,
|
|
931
2410
|
defaultImportRegistry,
|
|
932
2411
|
defaultIsEqual,
|
|
2412
|
+
deflateRaw,
|
|
2413
|
+
deleteSheetInFormula,
|
|
933
2414
|
describeBlockChange,
|
|
2415
|
+
describeConditionalFormat,
|
|
934
2416
|
describeConditionalTag,
|
|
2417
|
+
describeDataValidation,
|
|
935
2418
|
describeFormatChange,
|
|
936
2419
|
describeFormulaError,
|
|
937
2420
|
detectDelimiter,
|
|
938
2421
|
diffChanges,
|
|
939
2422
|
diffSequences,
|
|
940
2423
|
documentStructureCommandItems,
|
|
2424
|
+
docxFileName,
|
|
941
2425
|
docxImportAdapter,
|
|
942
2426
|
docxToDocumentImport,
|
|
2427
|
+
downloadBlob,
|
|
943
2428
|
escapeCsvField,
|
|
944
2429
|
escapeHtml,
|
|
945
2430
|
escapeVariableText,
|
|
2431
|
+
escapeXmlAttr,
|
|
2432
|
+
escapeXmlText,
|
|
946
2433
|
evaluateCondition,
|
|
947
2434
|
evaluateConditionExpression,
|
|
2435
|
+
evaluateConditionalFormats,
|
|
948
2436
|
evaluatePromptTokens,
|
|
949
2437
|
expandReplacement,
|
|
2438
|
+
exportDocx,
|
|
2439
|
+
exportDocxBlob,
|
|
950
2440
|
extractCellDependencies,
|
|
951
2441
|
extractInstructionNames,
|
|
952
2442
|
extractMentions,
|
|
953
2443
|
extractMentionsFromDoc,
|
|
2444
|
+
extractNameDependencies,
|
|
2445
|
+
extractReferenceDependencies,
|
|
954
2446
|
extractTemplateNames,
|
|
955
2447
|
extractVariableNames,
|
|
956
2448
|
extractVariables,
|
|
@@ -959,23 +2451,32 @@ export {
|
|
|
959
2451
|
findAllMatches,
|
|
960
2452
|
findAutocorrection,
|
|
961
2453
|
findCommentRanges,
|
|
2454
|
+
findDataValidation,
|
|
962
2455
|
findHexColors,
|
|
963
2456
|
findImportAdapter,
|
|
2457
|
+
findInvalidCells,
|
|
964
2458
|
findReplacePluginKey,
|
|
2459
|
+
findTextMentions,
|
|
965
2460
|
foldCodePoint,
|
|
966
2461
|
footnotesMarkdownIt,
|
|
967
2462
|
footnotesPluginKey,
|
|
2463
|
+
forEachRangeCell,
|
|
968
2464
|
formatCellDisplay,
|
|
969
2465
|
formatCellForDisplay,
|
|
970
2466
|
formatComparisonOperand,
|
|
971
2467
|
formatConditionalTag,
|
|
972
2468
|
formatFindStatus,
|
|
973
2469
|
formatGeneralFit,
|
|
2470
|
+
formatMentionText,
|
|
974
2471
|
formatNumberFormatValue,
|
|
975
2472
|
formatReviewTime,
|
|
2473
|
+
formatRuleRanges,
|
|
2474
|
+
formatSheetPrefix,
|
|
976
2475
|
formatTextFunction,
|
|
977
2476
|
formatValueWithCode,
|
|
2477
|
+
formulaIdentifiers,
|
|
978
2478
|
fractionRules,
|
|
2479
|
+
fullSpreadsheetViewWindow,
|
|
979
2480
|
getActiveHeading,
|
|
980
2481
|
getBookmarks,
|
|
981
2482
|
getClipboardData,
|
|
@@ -983,7 +2484,10 @@ export {
|
|
|
983
2484
|
getCommentAuthor,
|
|
984
2485
|
getCommentIdsAt,
|
|
985
2486
|
getCommentStore,
|
|
2487
|
+
getConditionalFormatCss,
|
|
2488
|
+
getConditionalFormatIcon,
|
|
986
2489
|
getCrossReferenceTargets,
|
|
2490
|
+
getDataBarCss,
|
|
987
2491
|
getDocumentStructureCommandItems,
|
|
988
2492
|
getEditorMarkdown,
|
|
989
2493
|
getEditorText,
|
|
@@ -999,18 +2503,28 @@ export {
|
|
|
999
2503
|
getFormulaSignatureParts,
|
|
1000
2504
|
getImportAccept,
|
|
1001
2505
|
getLatestVersion,
|
|
2506
|
+
getMentionNodes,
|
|
2507
|
+
getNameManagerRows,
|
|
1002
2508
|
getOutline,
|
|
2509
|
+
getParagraphStyleAt,
|
|
1003
2510
|
getPromptDiagnostics,
|
|
1004
2511
|
getRowSection,
|
|
1005
2512
|
getSchemaSignature,
|
|
2513
|
+
getSheetTabMenuItems,
|
|
1006
2514
|
getSpreadsheetMenuItems,
|
|
2515
|
+
getSpreadsheetScrollToCell,
|
|
2516
|
+
getSpreadsheetViewWindow,
|
|
2517
|
+
getStyleRegistry,
|
|
1007
2518
|
getSuppliedValue,
|
|
2519
|
+
getTableActionState,
|
|
1008
2520
|
getTableOfContentsEntries,
|
|
1009
2521
|
getTableSections,
|
|
2522
|
+
getTableState,
|
|
1010
2523
|
getTemplateBody,
|
|
1011
2524
|
getTrackChangesStore,
|
|
1012
2525
|
getTrackedChangeAt,
|
|
1013
2526
|
getTrackedChanges,
|
|
2527
|
+
getValidationListValues,
|
|
1014
2528
|
getVariableFormFields,
|
|
1015
2529
|
handleImageInsertion,
|
|
1016
2530
|
htmlImportAdapter,
|
|
@@ -1026,12 +2540,20 @@ export {
|
|
|
1026
2540
|
instructionRegex,
|
|
1027
2541
|
isBlankValue,
|
|
1028
2542
|
isFormulaError,
|
|
2543
|
+
isFormulaLambda,
|
|
1029
2544
|
isGeneralNumberFormat,
|
|
2545
|
+
isGfmTable,
|
|
1030
2546
|
isInsidePromptToken,
|
|
2547
|
+
isLambdaDefinition,
|
|
2548
|
+
isMoveSized,
|
|
2549
|
+
isParagraphStyleAvailable,
|
|
1031
2550
|
isPromptValueSet,
|
|
2551
|
+
isSelectionInTable,
|
|
1032
2552
|
isSingleCellRange,
|
|
2553
|
+
isTableEnabled,
|
|
1033
2554
|
isTrackChangesEnabled,
|
|
1034
2555
|
isUnsafeZipPath,
|
|
2556
|
+
isValidStyleId,
|
|
1035
2557
|
listFormulaFunctions,
|
|
1036
2558
|
mapFormulaReferences,
|
|
1037
2559
|
mapRawOffsetToResolved,
|
|
@@ -1041,16 +2563,22 @@ export {
|
|
|
1041
2563
|
matchConditionalTags,
|
|
1042
2564
|
matchFields,
|
|
1043
2565
|
matchesFilterRule,
|
|
2566
|
+
matchesTimePeriod,
|
|
2567
|
+
measureSpreadsheetView,
|
|
1044
2568
|
mergeRecords,
|
|
1045
2569
|
navigateToHeading,
|
|
2570
|
+
nextSheetName,
|
|
1046
2571
|
normalizeFieldKey,
|
|
1047
2572
|
normalizeFieldNames,
|
|
1048
2573
|
normalizeRange,
|
|
2574
|
+
normalizeTableCellAlignment,
|
|
2575
|
+
normalizeTableCellColor,
|
|
1049
2576
|
numberFormatColorToCss,
|
|
1050
2577
|
numberFormatForCellFormat,
|
|
1051
2578
|
numberToText,
|
|
1052
2579
|
offsetFormulaReferences,
|
|
1053
2580
|
outlinePluginKey,
|
|
2581
|
+
paragraphStylesPluginKey,
|
|
1054
2582
|
parseCellInput,
|
|
1055
2583
|
parseCellReference,
|
|
1056
2584
|
parseComparison,
|
|
@@ -1065,9 +2593,13 @@ export {
|
|
|
1065
2593
|
parseRange,
|
|
1066
2594
|
parseReplacement,
|
|
1067
2595
|
parseRichClipboardPayload,
|
|
2596
|
+
parseRuleRanges,
|
|
1068
2597
|
parseTsv,
|
|
1069
2598
|
parseVariableBody,
|
|
2599
|
+
pdfLayoutBlocksToHtml,
|
|
2600
|
+
pdfOperatorListToRules,
|
|
1070
2601
|
pdfTextItemsToParagraphs,
|
|
2602
|
+
pdfTextItemsToRuns,
|
|
1071
2603
|
pickImportFiles,
|
|
1072
2604
|
plainTextImportAdapter,
|
|
1073
2605
|
plainTextToParagraphHtml,
|
|
@@ -1075,8 +2607,11 @@ export {
|
|
|
1075
2607
|
plainTextToTipTapHtml,
|
|
1076
2608
|
preprocessMarkdownFileLinks,
|
|
1077
2609
|
preprocessMarkdownMentions,
|
|
2610
|
+
quoteSheetName,
|
|
1078
2611
|
rangeContains,
|
|
1079
2612
|
rangeContainsRange,
|
|
2613
|
+
rangeDependencyKey,
|
|
2614
|
+
rangesContain,
|
|
1080
2615
|
rangesIntersect,
|
|
1081
2616
|
readRichClipboard,
|
|
1082
2617
|
readSpreadsheetClipboard,
|
|
@@ -1088,6 +2623,8 @@ export {
|
|
|
1088
2623
|
registerSpreadsheetImportAdapters,
|
|
1089
2624
|
remapFormulaReferences,
|
|
1090
2625
|
removeImageNode,
|
|
2626
|
+
renameNameInFormula,
|
|
2627
|
+
renameSheetInFormula,
|
|
1091
2628
|
resolvePrompt,
|
|
1092
2629
|
resolveTemplates,
|
|
1093
2630
|
resolveTemplatesWithMapping,
|
|
@@ -1098,7 +2635,12 @@ export {
|
|
|
1098
2635
|
rowPassesFilters,
|
|
1099
2636
|
rtfImportAdapter,
|
|
1100
2637
|
rtfToPlainText,
|
|
2638
|
+
ruleAnchor,
|
|
2639
|
+
ruleFormulaAt,
|
|
1101
2640
|
runSpreadsheetMenuItem,
|
|
2641
|
+
runTableAction,
|
|
2642
|
+
safeCSSValue,
|
|
2643
|
+
sameSpreadsheetViewWindow,
|
|
1102
2644
|
sanitizeHtml,
|
|
1103
2645
|
sanitizeImportedHtml,
|
|
1104
2646
|
searchDocument,
|
|
@@ -1109,12 +2651,23 @@ export {
|
|
|
1109
2651
|
serializeMergeOutputs,
|
|
1110
2652
|
serializeRichClipboardPayload,
|
|
1111
2653
|
serializeTsv,
|
|
2654
|
+
setMentionRoleAt,
|
|
2655
|
+
setMentionRoleInText,
|
|
2656
|
+
sheetDropIndex,
|
|
2657
|
+
sheetNameNeedsQuotes,
|
|
1112
2658
|
shiftFormulaReferences,
|
|
2659
|
+
shiftRuleFormula,
|
|
2660
|
+
shouldShowTableBubbleMenu,
|
|
2661
|
+
shouldVirtualizeSpreadsheet,
|
|
1113
2662
|
smartQuoteRules,
|
|
1114
2663
|
smilieAutocorrectRules,
|
|
1115
2664
|
sortCompareValues,
|
|
1116
2665
|
sortZipEntryNames,
|
|
2666
|
+
stripInvalidXmlChars,
|
|
1117
2667
|
stripMarkdownCode,
|
|
2668
|
+
subtractRange,
|
|
2669
|
+
subtractRangeFromRanges,
|
|
2670
|
+
summarizeImportStructure,
|
|
1118
2671
|
symbolRules,
|
|
1119
2672
|
syncFootnotes,
|
|
1120
2673
|
tableOfContentsMarkdownIt,
|
|
@@ -1125,17 +2678,22 @@ export {
|
|
|
1125
2678
|
tokenizePrompt,
|
|
1126
2679
|
tokenizePromptWithDiagnostics,
|
|
1127
2680
|
trackChangesPluginKey,
|
|
2681
|
+
trackedChangeLabel,
|
|
1128
2682
|
tsvImportAdapter,
|
|
1129
2683
|
twoInitialCapitalsRules,
|
|
1130
2684
|
unescapeVariableText,
|
|
1131
2685
|
unregisterFormulaFunction,
|
|
1132
2686
|
unregisterImportAdapter,
|
|
1133
2687
|
updateImageSrc,
|
|
2688
|
+
validateCellInput,
|
|
2689
|
+
validateDefinedName,
|
|
1134
2690
|
validateFindPattern,
|
|
2691
|
+
validateSheetName,
|
|
1135
2692
|
variableRegex,
|
|
1136
2693
|
wildcardToRegExp,
|
|
1137
2694
|
withoutDirty,
|
|
1138
2695
|
writeRichClipboard,
|
|
2696
|
+
writeZip,
|
|
1139
2697
|
zipCrc32,
|
|
1140
2698
|
zipEntryTitle,
|
|
1141
2699
|
zipImportAdapter
|