@stll/folio-core 0.52.0 → 0.54.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 +23 -0
- package/dist/ai-edits/apply.d.ts +26 -1
- package/dist/ai-edits/apply.js +1779 -141
- package/dist/ai-edits/batch-claims.d.ts +145 -0
- package/dist/ai-edits/batch-claims.js +275 -0
- package/dist/ai-edits/blockRange.js +9 -3
- package/dist/ai-edits/character-boundaries.d.ts +43 -0
- package/dist/ai-edits/character-boundaries.js +95 -0
- package/dist/ai-edits/clean-text.d.ts +33 -3
- package/dist/ai-edits/clean-text.js +52 -6
- package/dist/ai-edits/comment-lifecycle.d.ts +18 -0
- package/dist/ai-edits/comment-lifecycle.js +52 -0
- package/dist/ai-edits/headless.d.ts +91 -7
- package/dist/ai-edits/headless.js +520 -51
- package/dist/ai-edits/index.d.ts +2 -1
- package/dist/ai-edits/index.js +2 -1
- package/dist/ai-edits/minimal-replacement.d.ts +21 -6
- package/dist/ai-edits/minimal-replacement.js +134 -15
- package/dist/ai-edits/newListNumbering.d.ts +23 -0
- package/dist/ai-edits/newListNumbering.js +94 -0
- package/dist/ai-edits/note-references.d.ts +96 -0
- package/dist/ai-edits/note-references.js +139 -0
- package/dist/ai-edits/pending-suggestions.d.ts +79 -0
- package/dist/ai-edits/pending-suggestions.js +306 -0
- package/dist/ai-edits/read.d.ts +6 -4
- package/dist/ai-edits/read.js +113 -50
- package/dist/ai-edits/result-validation.d.ts +29 -0
- package/dist/ai-edits/result-validation.js +164 -0
- package/dist/ai-edits/revisionStretches.d.ts +17 -0
- package/dist/ai-edits/revisionStretches.js +80 -0
- package/dist/ai-edits/snapshot.d.ts +36 -3
- package/dist/ai-edits/snapshot.js +180 -25
- package/dist/ai-edits/table-cell-mutations.d.ts +4 -2
- package/dist/ai-edits/table-cell-mutations.js +6 -2
- package/dist/ai-edits/table-geometry.d.ts +1 -1
- package/dist/ai-edits/table-row-column-mutations.d.ts +44 -17
- package/dist/ai-edits/table-row-column-mutations.js +86 -34
- package/dist/ai-edits/types.d.ts +155 -16
- package/dist/compare/compare.d.ts +1 -1
- package/dist/compare/compare.js +65 -16
- package/dist/compare/content-alignment.d.ts +5 -1
- package/dist/compare/content-alignment.js +52 -34
- package/dist/compare/content-types.d.ts +7 -0
- package/dist/compare/content.d.ts +4 -1
- package/dist/compare/content.js +6 -1
- package/dist/compare/formatting.js +2 -1
- package/dist/compare/inline-atoms.d.ts +21 -4
- package/dist/compare/inline-atoms.js +138 -16
- package/dist/compare/inline-provenance.js +1 -1
- package/dist/compare/plan.js +10 -5
- package/dist/compare/scenario.js +14 -3
- package/dist/compare/section-boundary-properties.js +1 -1
- package/dist/compare/types.d.ts +4 -2
- package/dist/compare/types.js +2 -1
- package/dist/compare/verification.d.ts +1 -1
- package/dist/compare/verification.js +15 -3
- package/dist/controller/committedLayoutDiff.d.ts +25 -0
- package/dist/controller/committedLayoutDiff.js +71 -0
- package/dist/controller/contentControlWidgetController.d.ts +1 -1
- package/dist/controller/folioEditor.d.ts +1 -1
- package/dist/controller/fontReadiness.d.ts +70 -3
- package/dist/controller/fontReadiness.js +100 -10
- package/dist/controller/headerFooterEditorManager.js +6 -1
- package/dist/controller/layoutPipeline.d.ts +12 -10
- package/dist/controller/layoutPipeline.js +65 -11
- package/dist/controller/layoutRunOptions.d.ts +24 -0
- package/dist/controller/layoutRunOptions.js +17 -0
- package/dist/controller/layoutScheduler.d.ts +19 -14
- package/dist/controller/layoutScheduler.js +15 -12
- package/dist/controller/layoutSession.d.ts +26 -2
- package/dist/controller/layoutSession.js +1 -1
- package/dist/controller/noteEditorManager.js +8 -3
- package/dist/document-operations.d.ts +11 -2
- package/dist/document-operations.js +230 -21
- package/dist/docx/altChunk.d.ts +8 -0
- package/dist/docx/altChunk.js +17 -0
- package/dist/docx/archiveInflation.d.ts +127 -0
- package/dist/docx/archiveInflation.js +181 -0
- package/dist/docx/attributeRemainder.d.ts +1 -1
- package/dist/docx/blockContentParser.d.ts +64 -1
- package/dist/docx/blockContentParser.js +17 -4
- package/dist/docx/blockCustomXmlShell.d.ts +7 -0
- package/dist/docx/blockCustomXmlShell.js +14 -0
- package/dist/docx/blockPlainText.js +7 -0
- package/dist/docx/commentAnchorIndex.js +1 -1
- package/dist/docx/commentRangeIntegrity.js +8 -3
- package/dist/docx/commentReferenceNormalization.js +1 -1
- package/dist/docx/commentReplyMarkers.js +20 -1
- package/dist/docx/compatibility.d.ts +1 -1
- package/dist/docx/compatibility.js +34 -13
- package/dist/docx/containerChildren.gen.d.ts +1 -1
- package/dist/docx/containerChildren.gen.js +1 -0
- package/dist/docx/documentParser.js +12 -12
- package/dist/docx/drawingIdNormalization.d.ts +3 -1
- package/dist/docx/drawingIdNormalization.js +6 -1
- package/dist/docx/ensureParaIds.js +119 -97
- package/dist/docx/footnoteParser.js +8 -4
- package/dist/docx/headerFooterParser.js +3 -3
- package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
- package/dist/docx/headerFooterReferenceNormalization.js +52 -27
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/listNumberingInstances.d.ts +59 -0
- package/dist/docx/listNumberingInstances.js +249 -0
- package/dist/docx/metadataPrivacy.js +24 -1
- package/dist/docx/normalizeBaseDirection.js +2 -1
- package/dist/docx/noteReferenceMark.d.ts +15 -0
- package/dist/docx/noteReferenceMark.js +48 -0
- package/dist/docx/opaqueCarrier.d.ts +7 -0
- package/dist/docx/opaqueCarrier.js +38 -0
- package/dist/docx/packageParts.js +4 -1
- package/dist/docx/paragraphParser.js +96 -27
- package/dist/docx/paragraphPropertySource.d.ts +4 -2
- package/dist/docx/paragraphPropertySource.js +10 -2
- package/dist/docx/paragraphTraversal.js +1 -0
- package/dist/docx/parseWarningMessage.js +4 -1
- package/dist/docx/parser.js +175 -22
- package/dist/docx/rezip.js +31 -7
- package/dist/docx/sdtProperties.js +1 -1
- package/dist/docx/sdtPropertiesPatch.js +3 -0
- package/dist/docx/selectiveSave.js +16 -9
- package/dist/docx/selectiveXmlPatch.d.ts +3 -1
- package/dist/docx/selectiveXmlPatch.js +186 -39
- package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
- package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
- package/dist/docx/serializer/documentSerializer.js +2 -0
- package/dist/docx/serializer/headerFooterSerializer.js +2 -0
- package/dist/docx/serializer/noteSerializer.js +3 -1
- package/dist/docx/serializer/paragraphSerializer.js +33 -9
- package/dist/docx/serializer/tableSerializer.js +25 -38
- package/dist/docx/server/boundedArchive.d.ts +8 -13
- package/dist/docx/server/boundedArchive.js +70 -59
- package/dist/docx/server/createBilingualDocument.js +3 -3
- package/dist/docx/server/extractDocxText.d.ts +8 -2
- package/dist/docx/server/extractDocxText.js +2 -2
- package/dist/docx/server/validateDocxConformance.d.ts +1 -1
- package/dist/docx/server/validateDocxConformance.js +1 -0
- package/dist/docx/tableParser.d.ts +157 -1
- package/dist/docx/tableParser.js +89 -10
- package/dist/docx/textBoxParser.js +1 -1
- package/dist/docx/unzip.d.ts +20 -2
- package/dist/docx/unzip.js +136 -25
- package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
- package/dist/docx/wordprocessingPrefixes.js +286 -0
- package/dist/fonts/embeddedFonts.js +1 -1
- package/dist/i18n/messages/catalogs.gen.d.ts +170 -34
- package/dist/i18n/messages/catalogs.gen.js +187 -51
- package/dist/i18n/messages/messages.gen.d.ts +10 -2
- package/dist/internal/compare/inline-presentation.d.ts +2 -1
- package/dist/internal/compare/inline-presentation.js +11 -10
- package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
- package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
- package/dist/internal/indexedPositionMap.d.ts +11 -0
- package/dist/internal/indexedPositionMap.js +42 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/revisionResolutionEdits.d.ts +13 -0
- package/dist/internal/revisionResolutionEdits.js +19 -0
- package/dist/internal/revisionResolutionInline.d.ts +24 -0
- package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
- package/dist/internal/revisionResolutionStep.d.ts +34 -0
- package/dist/internal/revisionResolutionStep.js +282 -0
- package/dist/internal/revisionResolutionTracking.d.ts +11 -0
- package/dist/internal/revisionResolutionTracking.js +124 -0
- package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
- package/dist/internal/wholeStoryRevisionResolution.js +600 -0
- package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
- package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
- package/dist/layout-bridge/convert/tableConversion.js +1 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
- package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
- package/dist/layout-engine/layoutInstrumentation.js +4 -1
- package/dist/layout-engine/measure/cache.d.ts +18 -1
- package/dist/layout-engine/measure/cache.js +31 -1
- package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
- package/dist/layout-engine/measure/measureContainer.js +7 -47
- package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
- package/dist/layout-engine/measure/measureHelpers.js +22 -2
- package/dist/layout-engine/measure/measureParagraph.js +2 -2
- package/dist/layout-engine/measure/measureWorker.js +2 -3
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
- package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
- package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
- package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
- package/dist/layout-engine/types.d.ts +6 -0
- package/dist/layout-painter/renderPage.js +1 -0
- package/dist/layout-painter/renderParagraph.js +1 -1
- package/dist/managers/ContextMenuManager.js +5 -2
- package/dist/managers/types.d.ts +3 -0
- package/dist/markdown/escape.d.ts +2 -2
- package/dist/markdown/escape.js +4 -5
- package/dist/markdown/fromMarkdown.js +2 -1
- package/dist/markdown/internals.d.ts +11 -1
- package/dist/markdown/internals.js +24 -3
- package/dist/markdown/renderBlock.js +121 -25
- package/dist/markdown/renderParagraph.d.ts +13 -1
- package/dist/markdown/renderParagraph.js +85 -38
- package/dist/markdown/renderRuns.d.ts +10 -1
- package/dist/markdown/renderRuns.js +323 -69
- package/dist/markdown/renderTable.js +24 -12
- package/dist/markdown/trailers.js +2 -2
- package/dist/markdown/types.d.ts +29 -7
- package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
- package/dist/paged-layout/incrementalMeasure.js +1 -9
- package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
- package/dist/paged-layout/transactionDirtyRange.js +29 -41
- package/dist/panel-layout.d.ts +83 -0
- package/dist/panel-layout.js +96 -0
- package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
- package/dist/prosemirror/anchoredTextBoxes.js +156 -0
- package/dist/prosemirror/attrs/index.d.ts +6 -2
- package/dist/prosemirror/attrs/index.js +172 -1
- package/dist/prosemirror/clearRunColor.d.ts +6 -0
- package/dist/prosemirror/clearRunColor.js +46 -0
- package/dist/prosemirror/commands/comments.d.ts +7 -8
- package/dist/prosemirror/commands/comments.js +281 -212
- package/dist/prosemirror/commands/contentControls.d.ts +1 -1
- package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
- package/dist/prosemirror/commands/formatPainter.js +1 -1
- package/dist/prosemirror/commands/formatting.d.ts +1 -1
- package/dist/prosemirror/commands/hyperlink.js +2 -1
- package/dist/prosemirror/commands/index.d.ts +2 -2
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/paragraph.d.ts +7 -1
- package/dist/prosemirror/commands/paragraph.js +9 -1
- package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
- package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
- package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
- package/dist/prosemirror/commands/propertyChangeScope.js +24 -3
- package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
- package/dist/prosemirror/commands/resolveAllTableChanges.js +620 -0
- package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
- package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.js +73 -0
- package/dist/prosemirror/commands/sectionBreak.js +2 -1
- package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +15 -2
- package/dist/prosemirror/commands/tableCellMergeResolution.js +23 -7
- package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
- package/dist/prosemirror/containerFinalParagraph.js +7 -6
- package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
- package/dist/prosemirror/conversion/fromProseDoc.js +177 -605
- package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -11
- package/dist/prosemirror/conversion/toProseDoc.js +70 -154
- package/dist/prosemirror/documentSchema.d.ts +8 -0
- package/dist/prosemirror/documentSchema.js +18 -0
- package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
- package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
- package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
- package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
- package/dist/prosemirror/extensions/StarterKit.js +5 -1
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +116 -63
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +4 -1
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +167 -128
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
- package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
- package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
- package/dist/prosemirror/extensions/features/pastedHtmlLists.js +124 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +33 -11
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
- package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +15 -8
- package/dist/prosemirror/extensions/marks/markUtils.js +25 -10
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +12 -0
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +46 -0
- package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
- package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +121 -226
- package/dist/prosemirror/extensions/types.d.ts +11 -1
- package/dist/prosemirror/findReplaceSelection.js +1 -1
- package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
- package/dist/prosemirror/hyperlinkRemoval.js +129 -0
- package/dist/prosemirror/index.d.ts +5 -3
- package/dist/prosemirror/index.js +5 -3
- package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
- package/dist/prosemirror/indexedNodeLookup.js +103 -0
- package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
- package/dist/prosemirror/listAutoformatMarkers.js +98 -0
- package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
- package/dist/prosemirror/listInstanceReferences.js +72 -0
- package/dist/prosemirror/listLabels.d.ts +24 -0
- package/dist/prosemirror/listLabels.js +111 -0
- package/dist/prosemirror/listNumbering.d.ts +92 -0
- package/dist/prosemirror/listNumbering.js +330 -0
- package/dist/prosemirror/listRendering.d.ts +27 -0
- package/dist/prosemirror/listRendering.js +27 -0
- package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
- package/dist/prosemirror/listRenderingAttrs.js +8 -1
- package/dist/prosemirror/markupViewNotes.d.ts +8 -0
- package/dist/prosemirror/markupViewNotes.js +49 -0
- package/dist/prosemirror/markupViewProjection.d.ts +97 -0
- package/dist/prosemirror/markupViewProjection.js +88 -0
- package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
- package/dist/prosemirror/noteReferenceReview.js +332 -0
- package/dist/prosemirror/numberingAttr.d.ts +9 -1
- package/dist/prosemirror/numberingAttr.js +9 -1
- package/dist/prosemirror/outlineLevelAttr.js +1 -1
- package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
- package/dist/prosemirror/paragraphIndentation.js +32 -7
- package/dist/prosemirror/paragraphMarkJoin.d.ts +21 -0
- package/dist/prosemirror/paragraphMarkJoin.js +26 -0
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
- package/dist/prosemirror/paragraphPropertyCarry.js +158 -0
- package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
- package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
- package/dist/prosemirror/plugins/documentNumbering.js +97 -11
- package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
- package/dist/prosemirror/plugins/documentStyleState.js +32 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +3 -13
- package/dist/prosemirror/plugins/documentStyles.js +67 -17
- package/dist/prosemirror/plugins/index.d.ts +2 -1
- package/dist/prosemirror/plugins/index.js +2 -1
- package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
- package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
- package/dist/prosemirror/plugins/suggestionMode.d.ts +27 -3
- package/dist/prosemirror/plugins/suggestionMode.js +490 -63
- package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
- package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
- package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
- package/dist/prosemirror/positionSweep.d.ts +24 -0
- package/dist/prosemirror/positionSweep.js +222 -0
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +23 -3
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
- package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
- package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
- package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
- package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
- package/dist/prosemirror/replacedAnnotations.js +170 -1
- package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
- package/dist/prosemirror/runFormattingFromMarks.js +567 -0
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
- package/dist/prosemirror/runFormattingReconciliation.js +10 -9
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/index.js +3 -0
- package/dist/prosemirror/schema/nodes.d.ts +44 -11
- package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
- package/dist/prosemirror/sectionMarkEdits.js +59 -0
- package/dist/prosemirror/storyListNumbering.d.ts +17 -0
- package/dist/prosemirror/storyListNumbering.js +102 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
- package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
- package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
- package/dist/prosemirror/tableCellPaste.d.ts +74 -0
- package/dist/prosemirror/tableCellPaste.js +525 -0
- package/dist/prosemirror/tableGridMutation.d.ts +87 -2
- package/dist/prosemirror/tableGridMutation.js +255 -2
- package/dist/prosemirror/tableRunIn.d.ts +51 -0
- package/dist/prosemirror/tableRunIn.js +165 -0
- package/dist/prosemirror/textInput.js +11 -2
- package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
- package/dist/prosemirror/trackedRevisionPath.js +32 -0
- package/dist/prosemirror/validation.js +5 -1
- package/dist/redline.js +93 -9
- package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
- package/dist/render-dom/BodySelectionOverlay.js +3 -2
- package/dist/server.d.ts +2 -2
- package/dist/utils/findReplace.js +2 -2
- package/dist/utils/mergeDocumentContent.js +1 -1
- package/dist/utils/noteReferenceLabels.d.ts +36 -0
- package/dist/utils/noteReferenceLabels.js +32 -0
- package/dist/utils/replaceText.js +1 -1
- package/dist/version-comparison.d.ts +1 -0
- package/dist/version-comparison.js +1 -0
- package/package.json +6 -5
- package/dist/internal/headlessRevisionResolution.d.ts +0 -23
|
@@ -14,7 +14,7 @@ import { serializeSdtWrapper } from "./sdtPropertiesSerializer.js";
|
|
|
14
14
|
import { serializeSectionProperties } from "./sectionPropertiesSerializer.js";
|
|
15
15
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
16
16
|
import { serializeTrackedChangeAttributes, trackedChangeAttributeRecord } from "./trackedChangeAttributes.js";
|
|
17
|
-
import { panic } from "better-result";
|
|
17
|
+
import { TaggedError, panic } from "better-result";
|
|
18
18
|
import { escapeXmlAttribute, escapeXmlText } from "@stll/docx-core";
|
|
19
19
|
import { PARAGRAPH_MARK_CHANGE_KINDS } from "@stll/docx-core/model";
|
|
20
20
|
import { SEQUENCE_CHILDREN } from "@stll/docx-core/schema";
|
|
@@ -315,27 +315,51 @@ function serializeSimpleField(field) {
|
|
|
315
315
|
}).join("");
|
|
316
316
|
return `<w:fldSimple ${attrs.join(" ")}>${contentXml}</w:fldSimple>`;
|
|
317
317
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
318
|
+
const replayableFormFieldDataXml = createCapturedXmlSanitizer({
|
|
319
|
+
allowedLocalNames: /* @__PURE__ */ new Set(["ffData"]),
|
|
320
|
+
allowedNamespaceUris: WORDPROCESSINGML_NAMESPACE,
|
|
321
|
+
inheritedNamespaceScope: OOXML_NAMESPACE_SCOPE
|
|
322
|
+
});
|
|
323
|
+
/** Serialize a complex field as structural fldChar runs and its content runs. */
|
|
323
324
|
function serializeComplexField(field) {
|
|
324
325
|
const parts = [];
|
|
325
326
|
const structuralFormatting = field.formatting ?? (field.fieldResultIsFallback ? void 0 : field.fieldResult[0]?.formatting);
|
|
326
327
|
const rPrXml = structuralFormatting ? serializeTextFormatting(structuralFormatting) : "";
|
|
327
328
|
const beginAttrs = ["w:fldCharType=\"begin\"", ...fieldStateAttributes(field)];
|
|
328
|
-
|
|
329
|
+
const formFieldDataXml = replayableFormFieldDataXml(field.formFieldDataXml);
|
|
330
|
+
const begin = formFieldDataXml ? `<w:fldChar ${beginAttrs.join(" ")}>${formFieldDataXml}</w:fldChar>` : `<w:fldChar ${beginAttrs.join(" ")}/>`;
|
|
331
|
+
parts.push(`<w:r>${rPrXml}${begin}</w:r>`);
|
|
329
332
|
if (field.fieldCode.length > 0) parts.push(...field.fieldCode.map((run) => serializeRun(run)));
|
|
330
333
|
else if (field.instruction.length > 0) {
|
|
331
334
|
const spaceAttr = field.instruction.startsWith(" ") || field.instruction.endsWith(" ") || field.instruction.includes(" ") ? " xml:space=\"preserve\"" : "";
|
|
332
335
|
parts.push(`<w:r>${rPrXml}<w:instrText${spaceAttr}>${escapeXmlText(field.instruction)}</w:instrText></w:r>`);
|
|
333
336
|
}
|
|
334
337
|
parts.push(`<w:r>${rPrXml}<w:fldChar w:fldCharType="separate"/></w:r>`);
|
|
335
|
-
if (!field.fieldResultIsFallback) parts.push(...field.fieldResult.map((run) => serializeRun(run)));
|
|
338
|
+
if (!field.fieldResultIsFallback || !formFieldDataXml) parts.push(...field.fieldResult.map((run) => serializeRun(run)));
|
|
336
339
|
parts.push(`<w:r>${rPrXml}<w:fldChar w:fldCharType="end"/></w:r>`);
|
|
337
340
|
return parts.join("");
|
|
338
341
|
}
|
|
342
|
+
var UnrepresentableTrackedSimpleFieldError = class extends TaggedError("UnrepresentableTrackedSimpleFieldError") {};
|
|
343
|
+
/** A revision can contain run-level field characters, but not `w:fldSimple`. */
|
|
344
|
+
function serializeTrackedSimpleField(field) {
|
|
345
|
+
const fieldResult = [];
|
|
346
|
+
for (const item of field.content) {
|
|
347
|
+
if (item.type !== "run") throw new UnrepresentableTrackedSimpleFieldError({
|
|
348
|
+
message: `A tracked simple field with ${item.type} result content cannot be serialized as valid OOXML.`,
|
|
349
|
+
contentType: item.type
|
|
350
|
+
});
|
|
351
|
+
fieldResult.push(item);
|
|
352
|
+
}
|
|
353
|
+
return serializeComplexField({
|
|
354
|
+
type: "complexField",
|
|
355
|
+
instruction: field.instruction,
|
|
356
|
+
fieldType: field.fieldType,
|
|
357
|
+
fieldCode: [],
|
|
358
|
+
fieldResult,
|
|
359
|
+
...field.fldLock !== void 0 && { fldLock: field.fldLock },
|
|
360
|
+
...field.dirty !== void 0 && { dirty: field.dirty }
|
|
361
|
+
});
|
|
362
|
+
}
|
|
339
363
|
/**
|
|
340
364
|
* Serialize an inline SDT (w:sdt).
|
|
341
365
|
*
|
|
@@ -413,7 +437,7 @@ function serializeTrackedChange(tag, change) {
|
|
|
413
437
|
case "run": return serializeContentRun(item);
|
|
414
438
|
case "simpleField":
|
|
415
439
|
case "complexField": {
|
|
416
|
-
const xml = item.type === "simpleField" ?
|
|
440
|
+
const xml = item.type === "simpleField" ? serializeTrackedSimpleField(item) : serializeComplexField(item);
|
|
417
441
|
return disposition === "removed" ? rewriteRunTextAsDeleted(xml) : xml;
|
|
418
442
|
}
|
|
419
443
|
case "mathEquation": return item.ommlXml;
|
|
@@ -6,6 +6,7 @@ import { TRANSITIONAL_NAME_BY_STRICT_NAME } from "../strictNames.gen.js";
|
|
|
6
6
|
import { TABLE_LOOK_FLAGS } from "../tableLook.js";
|
|
7
7
|
import { parseTableCellProperties, parseTableGrid, parseTableProperties, parseTablePropertyExceptions, parseTableRowProperties } from "../tableParser.js";
|
|
8
8
|
import { OOXML_NAMESPACE_SCOPE, parseXml } from "../xmlParser.js";
|
|
9
|
+
import { serializeBlockCustomXml } from "./blockCustomXmlSerializer.js";
|
|
9
10
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
10
11
|
import { serializeBorder } from "./borderSerializer.js";
|
|
11
12
|
import { serializeBookmarkMarker } from "./markupRangeAttributes.js";
|
|
@@ -456,56 +457,40 @@ const serializeTableGridChange = ({ id, columnWidths }) => {
|
|
|
456
457
|
const columns = columnWidths.map((width) => width === void 0 ? "<w:gridCol/>" : `<w:gridCol w:w="${intAttr(width)}"/>`).join("");
|
|
457
458
|
return `<w:tblGridChange w:id="${intAttr(id)}"><w:tblGrid>${columns}</w:tblGrid></w:tblGridChange>`;
|
|
458
459
|
};
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
*
|
|
462
|
-
* The control's record is on every child it held, so the wrapper is rebuilt
|
|
463
|
-
* by grouping consecutive children that name the same control. Equality is
|
|
464
|
-
* the record's canonical spelling rather than object identity, because the
|
|
465
|
-
* editor carries these records through JSON — a Yjs sync, a snapshot, a
|
|
466
|
-
* structured clone — and hands back an equal record rather than the same one.
|
|
467
|
-
* A wrapper that split in two there would mint a second `w:id` for one
|
|
468
|
-
* control, which is the defect, not the fix.
|
|
469
|
-
*
|
|
470
|
-
* The cost is the other direction: two adjacent rows the author put in two
|
|
471
|
-
* separate but identically spelled controls come back as one. Word mints a
|
|
472
|
-
* distinct `w:id` per control, so that needs a producer that writes none; the
|
|
473
|
-
* inline wrapper stack makes the same trade for the same reason.
|
|
474
|
-
*/
|
|
475
|
-
const contentControlKey = (properties) => canonicalJson(properties);
|
|
476
|
-
/**
|
|
477
|
-
* Re-open each control around the run of children that named it, outermost
|
|
478
|
-
* first.
|
|
479
|
-
*
|
|
480
|
-
* @param depth which layer of the stack this call is opening
|
|
481
|
-
*/
|
|
482
|
-
const serializeControlledChildren = (children, depth) => {
|
|
460
|
+
const tableCarrierKey = (carrier) => carrier.type === "customXml" ? `customXml:${String(carrier.wrapper.id)}` : `sdt:${canonicalJson(carrier.properties)}`;
|
|
461
|
+
const serializeTableCarriers = (children, depth = 0) => {
|
|
483
462
|
const parts = [];
|
|
484
463
|
let index = 0;
|
|
485
464
|
while (index < children.length) {
|
|
486
465
|
const child = children[index];
|
|
487
|
-
|
|
488
|
-
|
|
466
|
+
if (!child) break;
|
|
467
|
+
const carrier = child.carriers[depth];
|
|
468
|
+
if (!carrier) {
|
|
489
469
|
parts.push(child.xml);
|
|
490
470
|
index += 1;
|
|
491
471
|
continue;
|
|
492
472
|
}
|
|
493
|
-
const
|
|
473
|
+
const carrierKey = tableCarrierKey(carrier);
|
|
494
474
|
let end = index + 1;
|
|
495
475
|
while (end < children.length) {
|
|
496
|
-
const next = children[end]?.
|
|
497
|
-
if (next
|
|
476
|
+
const next = children[end]?.carriers[depth];
|
|
477
|
+
if ((next ? tableCarrierKey(next) : void 0) !== carrierKey) break;
|
|
498
478
|
end += 1;
|
|
499
479
|
}
|
|
500
|
-
const inner =
|
|
501
|
-
parts.push(
|
|
480
|
+
const inner = serializeTableCarriers(children.slice(index, end), depth + 1);
|
|
481
|
+
if (carrier.type === "customXml") parts.push(`${carrier.wrapper.openingXml}${inner}${carrier.wrapper.closingXml}`);
|
|
482
|
+
else parts.push(serializeSdtWrapper(carrier.properties, inner));
|
|
502
483
|
index = end;
|
|
503
484
|
}
|
|
504
485
|
return parts.join("");
|
|
505
486
|
};
|
|
487
|
+
const carriersFor = (value) => value.carrierStack ?? [...(value.contentControls ?? []).map((properties) => ({
|
|
488
|
+
type: "sdt",
|
|
489
|
+
properties
|
|
490
|
+
}))];
|
|
506
491
|
/** A capture from the sink, with the controls it sat inside when parsed. */
|
|
507
492
|
const preservedChild = (xml, child) => ({
|
|
508
|
-
|
|
493
|
+
carriers: carriersFor(child),
|
|
509
494
|
xml
|
|
510
495
|
});
|
|
511
496
|
/**
|
|
@@ -517,6 +502,7 @@ function serializeCellContent(content, serializeParagraph) {
|
|
|
517
502
|
case "paragraph": return serializeParagraph(block);
|
|
518
503
|
case "table": return serializeTable(block, serializeParagraph);
|
|
519
504
|
case "blockSdt": return serializeBlockSdt(block, serializeCellBlock);
|
|
505
|
+
case "blockCustomXml": return serializeBlockCustomXml(block, serializeCellBlock);
|
|
520
506
|
case "preservedBlock": return block.xml;
|
|
521
507
|
case "bookmarkStart":
|
|
522
508
|
case "bookmarkEnd": return serializeBookmarkMarker(block);
|
|
@@ -549,10 +535,11 @@ function serializeTableCell(cell, serializeParagraph) {
|
|
|
549
535
|
*/
|
|
550
536
|
const positionedChildren = (preserved, bookmarks) => {
|
|
551
537
|
if (bookmarks === void 0 || bookmarks.length === 0) return preserved;
|
|
552
|
-
return { children: [...preserved?.children ?? [], ...bookmarks.map(({ index, marker, contentControls }) => ({
|
|
538
|
+
return { children: [...preserved?.children ?? [], ...bookmarks.map(({ index, marker, contentControls, carrierStack }) => ({
|
|
553
539
|
index,
|
|
554
540
|
xml: serializeBookmarkMarker(marker),
|
|
555
|
-
...contentControls === void 0 ? {} : { contentControls }
|
|
541
|
+
...contentControls === void 0 ? {} : { contentControls },
|
|
542
|
+
...carrierStack === void 0 ? {} : { carrierStack }
|
|
556
543
|
}))] };
|
|
557
544
|
};
|
|
558
545
|
/**
|
|
@@ -564,8 +551,8 @@ function serializeTableRow(row, serializeParagraph) {
|
|
|
564
551
|
if (tblPrExXml) parts.push(tblPrExXml);
|
|
565
552
|
const trPrXml = serializeTableRowFormatting(row.formatting, row.propertyChanges, row.structuralChange);
|
|
566
553
|
if (trPrXml) parts.push(trPrXml);
|
|
567
|
-
parts.push(
|
|
568
|
-
|
|
554
|
+
parts.push(serializeTableCarriers(withPreservedChildren(row.cells.map((cell) => ({
|
|
555
|
+
carriers: carriersFor(cell),
|
|
569
556
|
xml: serializeTableCell(cell, serializeParagraph)
|
|
570
557
|
})), positionedChildren(row.preserved, row.bookmarks), preservedChild), 0));
|
|
571
558
|
const attrs = serializePreservedAttributes([], row.preservedAttributes);
|
|
@@ -581,8 +568,8 @@ function serializeTable(table, serializeParagraph) {
|
|
|
581
568
|
return `<w:tbl>${[
|
|
582
569
|
serializeTableFormatting(table.formatting, table.propertyChanges) || "<w:tblPr/>",
|
|
583
570
|
serializeTableGrid(table),
|
|
584
|
-
|
|
585
|
-
|
|
571
|
+
serializeTableCarriers(withPreservedChildren(table.rows.map((row) => ({
|
|
572
|
+
carriers: carriersFor(row),
|
|
586
573
|
xml: serializeTableRow(row, serializeParagraph)
|
|
587
574
|
})), positionedChildren(table.preserved, table.bookmarks), preservedChild), 0)
|
|
588
575
|
].join("")}</w:tbl>`;
|
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
import { XmlResourceLimits } from "../xmlResourceLimits.js";
|
|
2
|
-
import JSZip from "jszip";
|
|
3
2
|
//#region src/docx/server/boundedArchive.d.ts
|
|
4
|
-
declare module "jszip" {
|
|
5
|
-
interface JSZipObject {
|
|
6
|
-
/**
|
|
7
|
-
* Chunked read of the entry content, missing from the published typings.
|
|
8
|
-
* `nodeStream` is this stream wrapped in a Node.js `Readable`, which
|
|
9
|
-
* browsers and web workers cannot provide; the stream itself is
|
|
10
|
-
* platform-neutral.
|
|
11
|
-
*/
|
|
12
|
-
internalStream(type: "uint8array"): JSZip.JSZipStreamHelper<Uint8Array>;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
3
|
declare const DOCX_MAX_ENTRY_BYTES: number;
|
|
16
4
|
declare const DOCX_MAX_TOTAL_BYTES: number;
|
|
17
5
|
declare const DOCX_MAX_ENTRIES = 4096;
|
|
@@ -20,7 +8,7 @@ declare const DocxArchiveError_base: import("better-result").TaggedErrorClass<"D
|
|
|
20
8
|
/** Error raised when a DOCX archive cannot be loaded within configured limits. */
|
|
21
9
|
declare class DocxArchiveError extends DocxArchiveError_base<{
|
|
22
10
|
message: string;
|
|
23
|
-
reason: "load-failed" | "input-too-large" | "too-many-entries" | "entry-too-large" | "total-too-large" | "invalid-options";
|
|
11
|
+
reason: "load-failed" | "input-too-large" | "too-many-entries" | "entry-too-large" | "total-too-large" | "compression-ratio-exceeded" | "invalid-options";
|
|
24
12
|
cause?: unknown;
|
|
25
13
|
}> {}
|
|
26
14
|
type DocxArchiveOptions = {
|
|
@@ -28,6 +16,13 @@ type DocxArchiveOptions = {
|
|
|
28
16
|
maxEntryBytes?: number;
|
|
29
17
|
maxTotalBytes?: number;
|
|
30
18
|
maxEntries?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Most inflated bytes allowed per compressed byte, for each markup or text
|
|
21
|
+
* entry and for the package as a whole. Binary entries are bounded by the
|
|
22
|
+
* byte limits and the package ratio only, and entries and packages under
|
|
23
|
+
* 4 MiB inflated are exempt. Defaults to 200.
|
|
24
|
+
*/
|
|
25
|
+
maxCompressionRatio?: number;
|
|
31
26
|
/**
|
|
32
27
|
* Bounds on parsed XML structure, applied to every XML part this archive
|
|
33
28
|
* hands out as a string.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { compressionRatioLimitFor, countCentralDirectoryRecords, createInflationBudget, exceedsCompressionRatio, getZipEntrySizes, inflateEntryWithinLimits } from "../archiveInflation.js";
|
|
1
2
|
import { FOLIO_XML_RESOURCE_LIMITS, assertXmlResourceLimits, createXmlPackageBudget } from "../xmlResourceLimits.js";
|
|
2
3
|
import { TaggedError } from "better-result";
|
|
3
4
|
import JSZip from "jszip";
|
|
@@ -8,49 +9,26 @@ const DOCX_MAX_ENTRIES = 4096;
|
|
|
8
9
|
const DOCX_MAX_INPUT_BYTES = 50 * 1024 * 1024;
|
|
9
10
|
/** Error raised when a DOCX archive cannot be loaded within configured limits. */
|
|
10
11
|
var DocxArchiveError = class extends TaggedError("DocxArchiveError") {};
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const readLimitError = ({ limit, path, maxEntryBytes, maxTotalBytes, maxCompressionRatio }) => {
|
|
13
|
+
switch (limit) {
|
|
14
|
+
case "declared-size": return new DocxArchiveError({
|
|
15
|
+
message: `DOCX entry "${path}" inflated past its declared size`,
|
|
16
|
+
reason: "entry-too-large"
|
|
17
|
+
});
|
|
18
|
+
case "compression-ratio": return new DocxArchiveError({
|
|
19
|
+
message: `DOCX entry "${path}" exceeded the ${maxCompressionRatio}:1 compression ratio limit`,
|
|
20
|
+
reason: "compression-ratio-exceeded"
|
|
21
|
+
});
|
|
22
|
+
case "entry": return new DocxArchiveError({
|
|
23
|
+
message: `DOCX entry "${path}" exceeded the ${maxEntryBytes}-byte limit`,
|
|
24
|
+
reason: "entry-too-large"
|
|
25
|
+
});
|
|
26
|
+
case "total":
|
|
27
|
+
case "aborted": return new DocxArchiveError({
|
|
28
|
+
message: `DOCX archive exceeded the ${maxTotalBytes}-byte cumulative limit while reading "${path}"`,
|
|
29
|
+
reason: "total-too-large"
|
|
30
|
+
});
|
|
19
31
|
}
|
|
20
|
-
return merged;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Accumulate an entry chunk by chunk, checking both caps before each chunk is
|
|
24
|
-
* retained. Pausing the stream abandons a decompression bomb mid-inflate, so
|
|
25
|
-
* the caps bound memory instead of merely reporting the overrun afterwards.
|
|
26
|
-
*/
|
|
27
|
-
const collectStream = async ({ stream, maxEntryBytes, remainingBytes, maxTotalBytes, path }) => await new Promise((resolve, reject) => {
|
|
28
|
-
const chunks = [];
|
|
29
|
-
let entryBytes = 0;
|
|
30
|
-
const fail = (reason, message) => {
|
|
31
|
-
stream.pause();
|
|
32
|
-
reject(new DocxArchiveError({
|
|
33
|
-
message,
|
|
34
|
-
reason
|
|
35
|
-
}));
|
|
36
|
-
};
|
|
37
|
-
stream.on("data", (chunk) => {
|
|
38
|
-
entryBytes += chunk.length;
|
|
39
|
-
if (entryBytes > maxEntryBytes) {
|
|
40
|
-
fail("entry-too-large", `DOCX entry "${path}" exceeded the ${maxEntryBytes}-byte limit`);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (entryBytes > remainingBytes) {
|
|
44
|
-
fail("total-too-large", `DOCX archive exceeded the ${maxTotalBytes}-byte cumulative limit while reading "${path}"`);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
chunks.push(chunk);
|
|
48
|
-
}).on("end", () => resolve(concatChunks(chunks))).on("error", reject).resume();
|
|
49
|
-
});
|
|
50
|
-
const getDeclaredUncompressedBytes = (entry) => {
|
|
51
|
-
const data = "_data" in entry ? entry._data : void 0;
|
|
52
|
-
const declaredBytes = typeof data === "object" && data !== null && "uncompressedSize" in data ? data.uncompressedSize : void 0;
|
|
53
|
-
return typeof declaredBytes === "number" && Number.isFinite(declaredBytes) ? declaredBytes : null;
|
|
54
32
|
};
|
|
55
33
|
const resolveByteLimit = ({ value, fallback, name }) => {
|
|
56
34
|
const limit = value ?? fallback;
|
|
@@ -60,6 +38,7 @@ const resolveByteLimit = ({ value, fallback, name }) => {
|
|
|
60
38
|
});
|
|
61
39
|
return limit;
|
|
62
40
|
};
|
|
41
|
+
const asBytes = (bytes) => bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
63
42
|
const loadDocxArchive = async (bytes, options = {}) => {
|
|
64
43
|
const maxInputBytes = resolveByteLimit({
|
|
65
44
|
value: options.maxInputBytes,
|
|
@@ -81,10 +60,19 @@ const loadDocxArchive = async (bytes, options = {}) => {
|
|
|
81
60
|
fallback: DOCX_MAX_ENTRIES,
|
|
82
61
|
name: "DOCX entry limit"
|
|
83
62
|
});
|
|
63
|
+
const maxCompressionRatio = resolveByteLimit({
|
|
64
|
+
value: options.maxCompressionRatio,
|
|
65
|
+
fallback: 200,
|
|
66
|
+
name: "DOCX compression ratio limit"
|
|
67
|
+
});
|
|
84
68
|
if (bytes.byteLength > maxInputBytes) throw new DocxArchiveError({
|
|
85
69
|
message: `DOCX input contains ${bytes.byteLength} bytes (max ${maxInputBytes})`,
|
|
86
70
|
reason: "input-too-large"
|
|
87
71
|
});
|
|
72
|
+
if (countCentralDirectoryRecords(asBytes(bytes), maxEntries) > maxEntries) throw new DocxArchiveError({
|
|
73
|
+
message: `DOCX archive holds more than ${maxEntries} entries`,
|
|
74
|
+
reason: "too-many-entries"
|
|
75
|
+
});
|
|
88
76
|
let zip;
|
|
89
77
|
try {
|
|
90
78
|
zip = await JSZip.loadAsync(bytes);
|
|
@@ -101,30 +89,47 @@ const loadDocxArchive = async (bytes, options = {}) => {
|
|
|
101
89
|
reason: "too-many-entries"
|
|
102
90
|
});
|
|
103
91
|
let declaredTotalBytes = 0;
|
|
92
|
+
let declaredTotalKnown = true;
|
|
104
93
|
for (const entry of archiveEntries) {
|
|
105
94
|
if (entry.dir) continue;
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
108
|
-
|
|
109
|
-
|
|
95
|
+
const { compressedBytes, uncompressedBytes } = getZipEntrySizes(entry);
|
|
96
|
+
if (uncompressedBytes === null) {
|
|
97
|
+
declaredTotalKnown = false;
|
|
98
|
+
continue;
|
|
110
99
|
}
|
|
111
|
-
if (
|
|
112
|
-
message: `DOCX entry "${entry.name}" declares ${
|
|
100
|
+
if (uncompressedBytes > maxEntryBytes) throw new DocxArchiveError({
|
|
101
|
+
message: `DOCX entry "${entry.name}" declares ${uncompressedBytes} bytes (max ${maxEntryBytes})`,
|
|
113
102
|
reason: "entry-too-large"
|
|
114
103
|
});
|
|
115
|
-
|
|
104
|
+
if (exceedsCompressionRatio({
|
|
105
|
+
inflatedBytes: uncompressedBytes,
|
|
106
|
+
compressedBytes,
|
|
107
|
+
maxRatio: compressionRatioLimitFor(entry.name, maxCompressionRatio)
|
|
108
|
+
})) throw new DocxArchiveError({
|
|
109
|
+
message: `DOCX entry "${entry.name}" declares more than ${maxCompressionRatio} bytes per compressed byte`,
|
|
110
|
+
reason: "compression-ratio-exceeded"
|
|
111
|
+
});
|
|
112
|
+
declaredTotalBytes += uncompressedBytes;
|
|
116
113
|
}
|
|
117
|
-
if (
|
|
114
|
+
if (declaredTotalKnown && declaredTotalBytes > maxTotalBytes) throw new DocxArchiveError({
|
|
118
115
|
message: `DOCX archive declares ${declaredTotalBytes} cumulative bytes (max ${maxTotalBytes})`,
|
|
119
116
|
reason: "total-too-large"
|
|
120
117
|
});
|
|
118
|
+
if (exceedsCompressionRatio({
|
|
119
|
+
inflatedBytes: declaredTotalBytes,
|
|
120
|
+
compressedBytes: bytes.byteLength,
|
|
121
|
+
maxRatio: maxCompressionRatio
|
|
122
|
+
})) throw new DocxArchiveError({
|
|
123
|
+
message: `DOCX archive declares more than ${maxCompressionRatio} bytes per archive byte`,
|
|
124
|
+
reason: "compression-ratio-exceeded"
|
|
125
|
+
});
|
|
121
126
|
const xmlLimits = {
|
|
122
127
|
...FOLIO_XML_RESOURCE_LIMITS,
|
|
123
128
|
...options.xmlLimits
|
|
124
129
|
};
|
|
125
130
|
const xmlBudget = createXmlPackageBudget();
|
|
126
131
|
const countedParts = /* @__PURE__ */ new Set();
|
|
127
|
-
|
|
132
|
+
const inflationBudget = createInflationBudget(maxTotalBytes);
|
|
128
133
|
let readChain = Promise.resolve();
|
|
129
134
|
const readEntry = async (path, readOptions = {}) => {
|
|
130
135
|
const requestedMaxBytes = resolveByteLimit({
|
|
@@ -135,15 +140,21 @@ const loadDocxArchive = async (bytes, options = {}) => {
|
|
|
135
140
|
const work = async () => {
|
|
136
141
|
const entry = zip.file(path);
|
|
137
142
|
if (!entry) return null;
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
const entryLimit = Math.min(requestedMaxBytes, maxEntryBytes);
|
|
144
|
+
const result = await inflateEntryWithinLimits({
|
|
145
|
+
entry,
|
|
146
|
+
maxEntryBytes: entryLimit,
|
|
147
|
+
maxCompressionRatio: compressionRatioLimitFor(path, maxCompressionRatio),
|
|
148
|
+
budget: inflationBudget
|
|
149
|
+
});
|
|
150
|
+
if (!result.ok) throw readLimitError({
|
|
151
|
+
limit: result.limit,
|
|
152
|
+
path,
|
|
153
|
+
maxEntryBytes: entryLimit,
|
|
142
154
|
maxTotalBytes,
|
|
143
|
-
|
|
155
|
+
maxCompressionRatio
|
|
144
156
|
});
|
|
145
|
-
|
|
146
|
-
return content;
|
|
157
|
+
return result.bytes;
|
|
147
158
|
};
|
|
148
159
|
const next = readChain.then(work, work);
|
|
149
160
|
readChain = next.then(() => void 0, () => void 0);
|
|
@@ -154,7 +165,7 @@ const loadDocxArchive = async (bytes, options = {}) => {
|
|
|
154
165
|
entryMetadata: Object.freeze(archiveEntries.map((entry) => ({
|
|
155
166
|
path: entry.name,
|
|
156
167
|
directory: entry.dir,
|
|
157
|
-
declaredUncompressedBytes:
|
|
168
|
+
declaredUncompressedBytes: getZipEntrySizes(entry).uncompressedBytes
|
|
158
169
|
}))),
|
|
159
170
|
async readEntryString(path) {
|
|
160
171
|
const content = await readEntry(path);
|
|
@@ -203,7 +203,7 @@ const flattenBlocks = (content) => {
|
|
|
203
203
|
out.push(block);
|
|
204
204
|
return;
|
|
205
205
|
}
|
|
206
|
-
if (block.type !== "blockSdt") return;
|
|
206
|
+
if (block.type !== "blockSdt" && block.type !== "blockCustomXml") return;
|
|
207
207
|
for (const child of block.content) visit(child);
|
|
208
208
|
};
|
|
209
209
|
for (const block of content) visit(block);
|
|
@@ -467,7 +467,7 @@ const collectTableParagraphs = (table) => {
|
|
|
467
467
|
const collectBlocks = (blocks) => {
|
|
468
468
|
for (const item of blocks) if (item.type === "paragraph") out.push(item);
|
|
469
469
|
else if (item.type === "table") out.push(...collectTableParagraphs(item));
|
|
470
|
-
else if (item.type === "blockSdt") collectBlocks(item.content);
|
|
470
|
+
else if (item.type === "blockSdt" || item.type === "blockCustomXml") collectBlocks(item.content);
|
|
471
471
|
};
|
|
472
472
|
for (const row of table.rows) for (const cell of row.cells) collectBlocks(cell.content);
|
|
473
473
|
return out;
|
|
@@ -476,7 +476,7 @@ const cloneTableForTarget = ({ table, editableParagraphIds, paraIds, styleCloner
|
|
|
476
476
|
const paragraphs = [];
|
|
477
477
|
const cloneBlocks = (blocks) => blocks.map((item) => {
|
|
478
478
|
if (item.type === "table") return cloneTable(item);
|
|
479
|
-
if (item.type === "blockSdt") return {
|
|
479
|
+
if (item.type === "blockSdt" || item.type === "blockCustomXml") return {
|
|
480
480
|
...structuredClone(item),
|
|
481
481
|
content: cloneBlocks(item.content)
|
|
482
482
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DocxArchiveOptions } from "./boundedArchive.js";
|
|
1
2
|
//#region src/docx/server/extractDocxText.d.ts
|
|
2
3
|
/** Document part containing an extracted paragraph. */
|
|
3
4
|
type DocxParagraphSource = "header" | "body" | "footer";
|
|
@@ -59,7 +60,12 @@ type ExtractedDocxText = {
|
|
|
59
60
|
charCount: number;
|
|
60
61
|
view: "accepted";
|
|
61
62
|
};
|
|
63
|
+
/** Options for {@link extractDocxText}. */
|
|
64
|
+
type ExtractDocxTextOptions = {
|
|
65
|
+
/** Archive limits, applied before and while each part is inflated. */
|
|
66
|
+
readonly archive?: DocxArchiveOptions;
|
|
67
|
+
};
|
|
62
68
|
/** Extract paragraph text and formatting metadata from a DOCX archive. */
|
|
63
|
-
declare const extractDocxText: (bytes: ArrayBuffer | Uint8Array) => Promise<ExtractedDocxText>;
|
|
69
|
+
declare const extractDocxText: (bytes: ArrayBuffer | Uint8Array, options?: ExtractDocxTextOptions) => Promise<ExtractedDocxText>;
|
|
64
70
|
//#endregion
|
|
65
|
-
export { DocxParagraphSource, DocxTableRowKind, DocxTableRowPosition, ExtractedDocxParagraph, ExtractedDocxTableCell, ExtractedDocxTableCellParagraph, ExtractedDocxText, extractDocxText };
|
|
71
|
+
export { DocxParagraphSource, DocxTableRowKind, DocxTableRowPosition, ExtractDocxTextOptions, ExtractedDocxParagraph, ExtractedDocxTableCell, ExtractedDocxTableCellParagraph, ExtractedDocxText, extractDocxText };
|
|
@@ -504,8 +504,8 @@ const createEmptyResult = () => ({
|
|
|
504
504
|
view: "accepted"
|
|
505
505
|
});
|
|
506
506
|
/** Extract paragraph text and formatting metadata from a DOCX archive. */
|
|
507
|
-
const extractDocxText = async (bytes) => {
|
|
508
|
-
const archive = await loadDocxArchive(bytes);
|
|
507
|
+
const extractDocxText = async (bytes, options = {}) => {
|
|
508
|
+
const archive = await loadDocxArchive(bytes, options.archive);
|
|
509
509
|
const documentXml = await archive.readEntryString("word/document.xml");
|
|
510
510
|
if (documentXml === null) return createEmptyResult();
|
|
511
511
|
const root = parseXml(documentXml);
|
|
@@ -4,7 +4,7 @@ import { DocxArchiveOptions } from "./boundedArchive.js";
|
|
|
4
4
|
declare const FOLIO_DOCX_CONFORMANCE_REPORT_VERSION: 1;
|
|
5
5
|
declare const FOLIO_DOCX_CONFORMANCE_PROFILE: "folio-supported-v1";
|
|
6
6
|
declare const FOLIO_DOCX_CONFORMANCE_CHECKS: readonly ["archive-safety", "required-parts", "xml-well-formedness", "package-roots", "conformance-class", "canonical-model"];
|
|
7
|
-
declare const FOLIO_DOCX_CONFORMANCE_ISSUE_CODES: readonly ["archive-load-failed", "archive-invalid-options", "archive-input-too-large", "archive-too-many-entries", "archive-entry-too-large", "archive-total-too-large", "required-part-missing", "xml-doctype-forbidden", "xml-not-well-formed", "xml-read-failed", "required-xml-unreadable", "package-root-invalid", "conformance-class-unknown", "model-invalid", "model-warning", "parser-recovery", "parser-unsupported", "parser-failed", "encrypted-container", "container-not-zip"];
|
|
7
|
+
declare const FOLIO_DOCX_CONFORMANCE_ISSUE_CODES: readonly ["archive-load-failed", "archive-invalid-options", "archive-input-too-large", "archive-too-many-entries", "archive-entry-too-large", "archive-total-too-large", "archive-compression-ratio-exceeded", "required-part-missing", "xml-doctype-forbidden", "xml-not-well-formed", "xml-read-failed", "required-xml-unreadable", "package-root-invalid", "conformance-class-unknown", "model-invalid", "model-warning", "parser-recovery", "parser-unsupported", "parser-failed", "encrypted-container", "container-not-zip"];
|
|
8
8
|
type FolioDocxConformanceCheckId = (typeof FOLIO_DOCX_CONFORMANCE_CHECKS)[number];
|
|
9
9
|
type FolioDocxConformanceIssueCode = (typeof FOLIO_DOCX_CONFORMANCE_ISSUE_CODES)[number];
|
|
10
10
|
type FolioDocxConformanceCheckStatus = "passed" | "failed" | "indeterminate" | "not-run";
|
|
@@ -25,6 +25,7 @@ const FOLIO_DOCX_CONFORMANCE_ISSUE_CODES = Object.freeze([
|
|
|
25
25
|
"archive-too-many-entries",
|
|
26
26
|
"archive-entry-too-large",
|
|
27
27
|
"archive-total-too-large",
|
|
28
|
+
"archive-compression-ratio-exceeded",
|
|
28
29
|
"required-part-missing",
|
|
29
30
|
"xml-doctype-forbidden",
|
|
30
31
|
"xml-not-well-formed",
|