@stll/folio-core 0.45.0 → 0.47.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/dist/ai-edits/apply.js +85 -43
- package/dist/ai-edits/headless.js +2 -2
- package/dist/ai-edits/read.d.ts +1 -0
- package/dist/ai-edits/read.js +1 -0
- package/dist/ai-edits/snapshot.js +32 -27
- package/dist/ai-edits/table-cell-mutations.js +15 -7
- package/dist/ai-edits/table-geometry.js +21 -18
- package/dist/ai-edits/table-template.js +2 -2
- package/dist/compare/compare.js +2 -5
- package/dist/compare/content-alignment.js +108 -12
- package/dist/compare/content-types.d.ts +8 -2
- package/dist/compare/content.js +2 -11
- package/dist/compare/plan.js +7 -4
- package/dist/compare/scenario.js +2 -5
- package/dist/compare/section-boundary-properties.js +1 -2
- package/dist/compare/types.d.ts +9 -1
- package/dist/compare/types.js +12 -1
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/content-controls/checkboxDisplay.d.ts +17 -0
- package/dist/content-controls/checkboxDisplay.js +46 -0
- package/dist/content-controls/findContentControls.js +3 -1
- package/dist/content-controls/mutateContentControls.js +57 -43
- package/dist/controller/contentControlWidgetController.d.ts +1 -0
- package/dist/controller/contentControlWidgetController.js +3 -0
- package/dist/controller/hiddenEditorApi.js +3 -1
- package/dist/controller/hiddenEditorManager.d.ts +1 -1
- package/dist/controller/hiddenEditorManager.js +6 -3
- package/dist/controller/layoutPipeline.js +8 -3
- package/dist/display-list/build/buildDisplayList.js +20 -1
- package/dist/display-list/build/imagePrimitives.d.ts +4 -4
- package/dist/display-list/build/imagePrimitives.js +38 -18
- package/dist/display-list/build/pageBorderPrimitives.js +2 -1
- package/dist/display-list/build/paragraphPrimitives.js +113 -14
- package/dist/display-list/build/previewPrimitives.d.ts +10 -0
- package/dist/display-list/build/previewPrimitives.js +89 -0
- package/dist/display-list/build/strokes.d.ts +177 -8
- package/dist/display-list/build/strokes.js +167 -47
- package/dist/display-list/build/tablePrimitives.js +4 -2
- package/dist/display-list/build/textBoxPrimitives.js +6 -4
- package/dist/display-list/build/textDecorations.d.ts +15 -1
- package/dist/display-list/build/textDecorations.js +15 -1
- package/dist/display-list/dom/renderDisplayListToDom.js +11 -21
- package/dist/display-list/primitives.d.ts +13 -2
- package/dist/display-list/primitives.js +36 -1
- package/dist/display-list/types.d.ts +17 -0
- package/dist/document-operations.js +2 -1
- package/dist/docx/attributeRemainder.d.ts +76 -0
- package/dist/docx/attributeRemainder.js +111 -0
- package/dist/docx/blockContentParser.d.ts +3 -1
- package/dist/docx/blockContentParser.js +102 -106
- package/dist/docx/blockPlainText.d.ts +3 -4
- package/dist/docx/blockPlainText.js +3 -0
- package/dist/docx/borderParser.js +26 -11
- package/dist/docx/builtInStyles.d.ts +8 -16
- package/dist/docx/builtInStyles.js +54 -17
- package/dist/docx/commentAnchorIndex.d.ts +30 -0
- package/dist/docx/commentAnchorIndex.js +50 -0
- package/dist/docx/commentParser.d.ts +1 -1
- package/dist/docx/commentParser.js +56 -39
- package/dist/docx/commentRangeIntegrity.d.ts +16 -1
- package/dist/docx/commentRangeIntegrity.js +42 -1
- package/dist/docx/commentRangeJoin.d.ts +9 -0
- package/dist/docx/commentRangeJoin.js +33 -0
- package/dist/docx/commentReferenceCompletion.d.ts +9 -0
- package/dist/docx/commentReferenceCompletion.js +47 -0
- package/dist/docx/commentReferenceNormalization.js +3 -1
- package/dist/docx/commentReplyMarkers.js +11 -19
- package/dist/docx/compatibility.js +56 -41
- package/dist/docx/containerChildren.d.ts +208 -0
- package/dist/docx/containerChildren.gen.d.ts +43 -0
- package/dist/docx/containerChildren.gen.js +263 -0
- package/dist/docx/containerChildren.js +153 -0
- package/dist/docx/diagramPreview.d.ts +14 -2
- package/dist/docx/diagramPreview.js +81 -169
- package/dist/docx/documentParser.d.ts +1 -1
- package/dist/docx/documentParser.js +7 -4
- package/dist/docx/drawingAnchor.d.ts +87 -0
- package/dist/docx/drawingAnchor.js +201 -0
- package/dist/docx/drawingUtils.d.ts +43 -38
- package/dist/docx/drawingUtils.js +205 -118
- package/dist/docx/ensureParaIds.js +17 -7
- package/dist/docx/fieldParser.d.ts +1 -1
- package/dist/docx/fieldParser.js +4 -4
- package/dist/docx/fieldState.d.ts +26 -0
- package/dist/docx/fieldState.js +53 -0
- package/dist/docx/fontTableParser.js +102 -41
- package/dist/docx/footnoteParser.d.ts +1 -1
- package/dist/docx/footnoteParser.js +10 -6
- package/dist/docx/graphicFrameLocks.d.ts +16 -4
- package/dist/docx/graphicFrameLocks.js +19 -6
- package/dist/docx/groupDrawingParser.js +4 -3
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/headerFooterReferenceNormalization.js +1 -0
- package/dist/docx/hyperlinkParser.d.ts +66 -9
- package/dist/docx/hyperlinkParser.js +153 -26
- package/dist/docx/imageParser.js +160 -115
- package/dist/docx/index.d.ts +2 -1
- package/dist/docx/index.js +2 -1
- package/dist/docx/inlineContentRemovals.d.ts +28 -0
- package/dist/docx/inlineContentRemovals.js +46 -0
- package/dist/docx/inlineWrapperContent.d.ts +166 -0
- package/dist/docx/inlineWrapperContent.js +165 -0
- package/dist/docx/inlineWrapperParser.d.ts +11 -0
- package/dist/docx/inlineWrapperParser.js +60 -0
- package/dist/docx/nonVisualDrawingProps.d.ts +5 -13
- package/dist/docx/normalizeBaseDirection.js +12 -1
- package/dist/docx/numberingParser.d.ts +25 -2
- package/dist/docx/numberingParser.js +264 -361
- package/dist/docx/numberingReference.d.ts +9 -16
- package/dist/docx/numberingReference.js +17 -16
- package/dist/docx/numberingReferenceNormalization.js +7 -7
- package/dist/docx/ooxmlCounterFormatter.d.ts +1 -1
- package/dist/docx/ooxmlCounterFormatter.js +4 -1
- package/dist/docx/paraIdAttribute.d.ts +111 -0
- package/dist/docx/paraIdAttribute.js +142 -0
- package/dist/docx/paragraphParser.d.ts +10 -25
- package/dist/docx/paragraphParser.js +421 -496
- package/dist/docx/paragraphProperties.d.ts +23 -0
- package/dist/docx/paragraphProperties.js +279 -0
- package/dist/docx/paragraphPropertySource.js +7 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +3 -2
- package/dist/docx/paragraphTextBoxEnrichment.js +20 -59
- package/dist/docx/paragraphTraversal.d.ts +14 -10
- package/dist/docx/paragraphTraversal.js +53 -52
- package/dist/docx/parseWarningMessage.js +5 -1
- package/dist/docx/parserEnums.d.ts +6 -8
- package/dist/docx/parserEnums.js +4 -6
- package/dist/docx/preservedRunContent.d.ts +32 -0
- package/dist/docx/preservedRunContent.js +96 -0
- package/dist/docx/previewBudget.d.ts +44 -23
- package/dist/docx/previewBudget.js +61 -30
- package/dist/docx/propertyElementAttributes.d.ts +178 -0
- package/dist/docx/propertyElementAttributes.js +114 -0
- package/dist/docx/renderedPageBreakNormalization.js +4 -6
- package/dist/docx/rezip.d.ts +28 -2
- package/dist/docx/rezip.js +152 -27
- package/dist/docx/runConsolidator.d.ts +42 -2
- package/dist/docx/runConsolidator.js +60 -6
- package/dist/docx/runParser.d.ts +55 -19
- package/dist/docx/runParser.js +394 -306
- package/dist/docx/runPayload.d.ts +5 -0
- package/dist/docx/runPayload.js +4 -0
- package/dist/docx/sdtProperties.d.ts +39 -5
- package/dist/docx/sdtProperties.js +205 -84
- package/dist/docx/sdtPropertiesPatch.d.ts +5 -9
- package/dist/docx/sdtPropertiesPatch.js +68 -112
- package/dist/docx/sectionParser.d.ts +1 -2
- package/dist/docx/sectionParser.js +241 -238
- package/dist/docx/selectiveSave.js +3 -2
- package/dist/docx/selectiveXmlPatch.d.ts +66 -3
- package/dist/docx/selectiveXmlPatch.js +276 -133
- package/dist/docx/serializer/blockSdtSerializer.js +2 -96
- package/dist/docx/serializer/borderSerializer.d.ts +5 -5
- package/dist/docx/serializer/borderSerializer.js +12 -10
- package/dist/docx/serializer/commentSerializer.js +5 -7
- package/dist/docx/serializer/documentSerializer.js +11 -11
- package/dist/docx/serializer/fontTableSerializer.js +31 -3
- package/dist/docx/serializer/headerFooterSerializer.js +10 -9
- package/dist/docx/serializer/markupRangeAttributes.d.ts +9 -1
- package/dist/docx/serializer/markupRangeAttributes.js +9 -1
- package/dist/docx/serializer/noteSerializer.js +11 -8
- package/dist/docx/serializer/numberingSerializer.d.ts +1 -6
- package/dist/docx/serializer/numberingSerializer.js +81 -79
- package/dist/docx/serializer/paragraphSerializer.d.ts +1 -9
- package/dist/docx/serializer/paragraphSerializer.js +156 -236
- package/dist/docx/serializer/runSerializer.d.ts +1 -5
- package/dist/docx/serializer/runSerializer.js +134 -75
- package/dist/docx/serializer/sdtPropertiesSerializer.d.ts +26 -0
- package/dist/docx/serializer/sdtPropertiesSerializer.js +111 -0
- package/dist/docx/serializer/sectionPropertiesSerializer.js +42 -49
- package/dist/docx/serializer/settingsSerializer.js +6 -4
- package/dist/docx/serializer/stylesSerializer.js +8 -11
- package/dist/docx/serializer/tableSerializer.js +283 -105
- package/dist/docx/serializer/textFormattingSerializer.d.ts +28 -4
- package/dist/docx/serializer/textFormattingSerializer.js +111 -101
- package/dist/docx/serializer/xmlUtils.d.ts +1 -1
- package/dist/docx/serializer/xmlUtils.js +1 -1
- package/dist/docx/server/createBilingualDocument.js +20 -16
- package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
- package/dist/docx/server/materializeYjsDocx.js +9 -1
- package/dist/docx/server/migrateYjsAttrSchema.d.ts +55 -0
- package/dist/docx/server/migrateYjsAttrSchema.js +95 -0
- package/dist/docx/settingsParser.js +7 -4
- package/dist/docx/shadingParser.d.ts +2 -1
- package/dist/docx/shadingParser.js +43 -7
- package/dist/docx/shapeParser.js +13 -8
- package/dist/docx/strictNames.d.ts +11 -0
- package/dist/docx/strictNames.gen.d.ts +45 -0
- package/dist/docx/strictNames.gen.js +50 -0
- package/dist/docx/strictNames.js +43 -0
- package/dist/docx/strictValueEncodings.gen.js +133 -131
- package/dist/docx/styleParser.js +17 -349
- package/dist/docx/tableParser.d.ts +11 -2
- package/dist/docx/tableParser.js +665 -220
- package/dist/docx/textBoxParser.d.ts +28 -3
- package/dist/docx/textBoxParser.js +69 -9
- package/dist/docx/themeColorAttribute.d.ts +13 -0
- package/dist/docx/themeColorAttribute.js +24 -0
- package/dist/docx/trackedMoveRangeNormalization.js +2 -1
- package/dist/docx/unzip.js +5 -4
- package/dist/docx/vmlImageParser.d.ts +30 -5
- package/dist/docx/vmlImageParser.js +91 -32
- package/dist/docx/vmlPreview.js +2 -2
- package/dist/docx/wrapPolygon.d.ts +30 -0
- package/dist/docx/wrapPolygon.js +70 -0
- package/dist/docx/xmlEncoding.d.ts +5 -0
- package/dist/docx/xmlEncoding.js +12 -0
- package/dist/docx/xmlParser.d.ts +23 -1
- package/dist/docx/xmlParser.js +31 -2
- package/dist/fonts/embeddedFonts.js +3 -3
- package/dist/headless-layout.js +12 -1
- package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
- package/dist/i18n/messages/catalogs.gen.js +102 -34
- package/dist/i18n/messages/messages.gen.d.ts +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/headlessRevisionResolution.js +9 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +7 -2
- package/dist/internal/paragraphFormattingSerialization.d.ts +20 -9
- package/dist/internal/paragraphFormattingSerialization.js +118 -83
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +17 -12
- package/dist/layout-bridge/convert/toFlowBlocks.js +267 -101
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +53 -17
- package/dist/layout-engine/measure/measureBlocks.d.ts +3 -0
- package/dist/layout-engine/measure/measureBlocks.js +6 -10
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +2 -0
- package/dist/layout-engine/measure/tableCellGrid.js +2 -1
- package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +2 -1
- package/dist/layout-engine/measure/tableInlinePlacement.js +2 -5
- package/dist/layout-engine/paragraphSequence.js +3 -2
- package/dist/layout-engine/renderedBreakReconciliation.js +2 -1
- package/dist/layout-engine/section-breaks.d.ts +49 -2
- package/dist/layout-engine/section-breaks.js +55 -4
- package/dist/layout-engine/types.d.ts +69 -17
- package/dist/layout-engine/types.js +16 -1
- package/dist/layout-painter/borderStroke.d.ts +18 -4
- package/dist/layout-painter/renderImage.d.ts +5 -1
- package/dist/layout-painter/renderImage.js +10 -3
- package/dist/layout-painter/renderPage.d.ts +2 -0
- package/dist/layout-painter/renderPage.js +10 -4
- package/dist/layout-painter/renderParagraph.d.ts +14 -1
- package/dist/layout-painter/renderParagraph.js +34 -28
- package/dist/layout-painter/renderTable.d.ts +4 -1
- package/dist/layout-painter/renderTable.js +22 -22
- package/dist/layout-painter/renderTextBox.js +5 -3
- package/dist/managers/autoSaveCodec.d.ts +9 -1
- package/dist/managers/autoSaveCodec.js +12 -4
- package/dist/markdown/renderBlock.js +3 -0
- package/dist/markdown/renderRuns.d.ts +1 -1
- package/dist/markdown/renderRuns.js +34 -6
- package/dist/markdown/renderTable.js +24 -6
- package/dist/markdown/trailers.js +4 -1
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
- package/dist/paged-layout/sectionBlockWidths.js +26 -4
- package/dist/pdf/images.js +142 -6
- package/dist/prosemirror/attrs/index.d.ts +34 -5
- package/dist/prosemirror/attrs/index.js +639 -48
- package/dist/prosemirror/authoredTransformAttrs.d.ts +28 -0
- package/dist/prosemirror/authoredTransformAttrs.js +64 -0
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +9 -1
- package/dist/prosemirror/bookmarkBoundaryAttrs.js +22 -3
- package/dist/prosemirror/commands/comments.js +68 -53
- package/dist/prosemirror/commands/contentControls.js +33 -20
- package/dist/prosemirror/commands/image.d.ts +10 -3
- package/dist/prosemirror/commands/image.js +46 -29
- package/dist/prosemirror/commands/pageBreak.js +1 -1
- package/dist/prosemirror/commands/paragraph.d.ts +2 -1
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +12 -4
- package/dist/prosemirror/commands/propertyChangeScope.js +22 -4
- package/dist/prosemirror/commands/sectionBreak.d.ts +33 -1
- package/dist/prosemirror/commands/sectionBreak.js +187 -11
- package/dist/prosemirror/commentReferenceAttrs.d.ts +8 -0
- package/dist/prosemirror/commentReferenceAttrs.js +33 -0
- package/dist/prosemirror/commentReferenceIntegrity.d.ts +47 -0
- package/dist/prosemirror/commentReferenceIntegrity.js +43 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +17 -12
- package/dist/prosemirror/conversion/fromProseDoc.js +553 -207
- package/dist/prosemirror/conversion/index.d.ts +2 -2
- package/dist/prosemirror/conversion/preservedSinkCarriers.d.ts +39 -0
- package/dist/prosemirror/conversion/preservedSinkCarriers.js +19 -0
- package/dist/prosemirror/conversion/runShadingMark.js +14 -1
- package/dist/prosemirror/conversion/sdtAttrs.d.ts +10 -1
- package/dist/prosemirror/conversion/sdtAttrs.js +19 -5
- package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -9
- package/dist/prosemirror/conversion/toProseDoc.js +801 -411
- package/dist/prosemirror/emptyRangeAnchor.d.ts +53 -0
- package/dist/prosemirror/emptyRangeAnchor.js +158 -0
- package/dist/prosemirror/extensions/StarterKit.js +14 -58
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +21 -16
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +48 -29
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -1
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +5 -3
- package/dist/prosemirror/extensions/features/ListExtension.js +43 -24
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -0
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +4 -3
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +3 -3
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +5 -5
- package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +3 -1
- package/dist/prosemirror/extensions/features/pasteCleanup.js +56 -2
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +5 -4
- package/dist/prosemirror/extensions/markRegistry.d.ts +65 -0
- package/dist/prosemirror/extensions/markRegistry.js +138 -0
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.d.ts +18 -0
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +77 -0
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +26 -0
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +134 -0
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -1
- package/dist/prosemirror/extensions/marks/UnderlineExtension.js +12 -18
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +49 -5
- package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.d.ts +29 -0
- package/dist/prosemirror/extensions/nodes/BlockBookmarkBoundaryExtension.js +46 -0
- package/dist/prosemirror/extensions/nodes/BlockSdtExtension.d.ts +4 -3
- package/dist/prosemirror/extensions/nodes/BlockSdtExtension.js +18 -13
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +28 -53
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.d.ts +11 -0
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +97 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +9 -7
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +24 -1
- package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.d.ts +11 -0
- package/dist/prosemirror/extensions/nodes/MoveRangeBoundaryExtension.js +43 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.d.ts +32 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +67 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.d.ts +16 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +60 -0
- package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/nodes/RangeAnchorExtension.js +65 -0
- package/dist/prosemirror/extensions/nodes/SdtExtension.d.ts +3 -1
- package/dist/prosemirror/extensions/nodes/SdtExtension.js +22 -16
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +7 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +142 -123
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +9 -1
- package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.d.ts +23 -0
- package/dist/prosemirror/extensions/nodes/bookmarkBoundaryDom.js +57 -0
- package/dist/prosemirror/extensions/types.d.ts +12 -3
- package/dist/prosemirror/index.d.ts +4 -2
- package/dist/prosemirror/index.js +2 -1
- package/dist/prosemirror/inlineWrapperStack.d.ts +39 -0
- package/dist/prosemirror/inlineWrapperStack.js +92 -0
- package/dist/prosemirror/listMarker.d.ts +2 -2
- package/dist/prosemirror/listMarker.js +7 -8
- package/dist/prosemirror/listRenderingAttrs.js +11 -1
- package/dist/prosemirror/listState.d.ts +62 -0
- package/dist/prosemirror/listState.js +49 -0
- package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +13 -0
- package/dist/prosemirror/moveRangeBoundaryAttrs.js +114 -0
- package/dist/prosemirror/numberedRefFields.js +4 -4
- package/dist/prosemirror/numberingAttr.d.ts +55 -0
- package/dist/prosemirror/numberingAttr.js +74 -0
- package/dist/prosemirror/outlineLevelAttr.d.ts +29 -0
- package/dist/prosemirror/outlineLevelAttr.js +42 -0
- package/dist/prosemirror/pageBreakRunProjection.d.ts +17 -7
- package/dist/prosemirror/pageBreakRunProjection.js +19 -9
- package/dist/prosemirror/paragraphFormattingProvenance.d.ts +9 -0
- package/dist/prosemirror/paragraphFormattingProvenance.js +4 -1
- package/dist/prosemirror/plugins/selectionTracker.d.ts +3 -6
- package/dist/prosemirror/plugins/selectionTracker.js +3 -10
- package/dist/prosemirror/rangeAnchorAttrs.d.ts +14 -0
- package/dist/prosemirror/rangeAnchorAttrs.js +101 -0
- package/dist/prosemirror/replacedAnnotations.d.ts +59 -0
- package/dist/prosemirror/replacedAnnotations.js +183 -0
- package/dist/prosemirror/revisionCarriers.d.ts +86 -2
- package/dist/prosemirror/revisionCarriers.js +86 -60
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +5 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +7 -1
- package/dist/prosemirror/runIdentity.d.ts +28 -0
- package/dist/prosemirror/runIdentity.js +36 -0
- package/dist/prosemirror/runStyleFormatting.js +1 -1
- package/dist/prosemirror/schema/index.d.ts +3 -3
- package/dist/prosemirror/schema/marks.d.ts +47 -4
- package/dist/prosemirror/schema/nodes.d.ts +309 -26
- package/dist/prosemirror/schema/nodes.js +16 -1
- package/dist/prosemirror/sectionCarrier.d.ts +37 -0
- package/dist/prosemirror/sectionCarrier.js +40 -0
- package/dist/prosemirror/selectionState.d.ts +3 -0
- package/dist/prosemirror/selectionState.js +4 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +5 -4
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +15 -13
- package/dist/prosemirror/tableResize.js +5 -6
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +4 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +4 -0
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +10 -11
- package/dist/prosemirror/utils/extractTrackedChanges.js +109 -92
- package/dist/prosemirror/validation.js +31 -6
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +73 -0
- package/dist/prosemirror/yjsDocumentMetadata.js +592 -0
- package/dist/prosemirror/zeroWidthAnchors.js +6 -0
- package/dist/render-dom/commentAnchorAttributes.d.ts +37 -0
- package/dist/render-dom/commentAnchorAttributes.js +54 -0
- package/dist/server.d.ts +3 -1
- package/dist/server.js +3 -1
- package/dist/style-sets/extract.js +4 -4
- package/dist/style-sets/stellaStyle.js +36 -23
- package/dist/types/colors.d.ts +2 -2
- package/dist/types/content.d.ts +2 -2
- package/dist/types/documentEnumValues.d.ts +53 -26
- package/dist/types/documentEnumValues.js +72 -174
- package/dist/types/formatting.d.ts +2 -2
- package/dist/types/index.d.ts +9 -2
- package/dist/utils/borderCss.d.ts +246 -0
- package/dist/utils/borderCss.js +325 -0
- package/dist/utils/clipboard.d.ts +9 -1
- package/dist/utils/clipboard.js +27 -1
- package/dist/utils/colorResolver.d.ts +4 -3
- package/dist/utils/colorResolver.js +45 -76
- package/dist/utils/createDocument.js +24 -6
- package/dist/utils/findReplace.js +52 -10
- package/dist/utils/formatToStyle.d.ts +84 -2
- package/dist/utils/formatToStyle.js +133 -52
- package/dist/utils/headingCollector.js +3 -2
- package/dist/utils/imageLuminance.d.ts +15 -0
- package/dist/utils/imageLuminance.js +32 -0
- package/dist/utils/mergeDocumentContent.js +12 -20
- package/dist/utils/paragraphFormattingMerge.js +27 -6
- package/dist/utils/replaceText.js +1 -0
- package/dist/utils/tableOperations.d.ts +5 -3
- package/dist/utils/tableOperations.js +14 -1
- package/dist/utils/tablePlacement.d.ts +7 -0
- package/dist/utils/tablePlacement.js +14 -0
- package/dist/utils/textDirectionFlow.d.ts +15 -0
- package/dist/utils/textDirectionFlow.js +38 -0
- package/dist/utils/textFormattingMerge.js +16 -4
- package/package.json +10 -10
- package/dist/ai-edits/__fixtures__/paragraphs.d.ts +0 -17
- package/dist/ai-edits/__fixtures__/paragraphs.js +0 -33
- package/dist/compare/__fixtures__/body-sequence.d.ts +0 -119
- package/dist/compare/__fixtures__/body-sequence.js +0 -225
- package/dist/compare/__fixtures__/nested-table.d.ts +0 -16
- package/dist/compare/__fixtures__/nested-table.js +0 -50
- package/dist/compare/__fixtures__/numbered-list.d.ts +0 -34
- package/dist/compare/__fixtures__/numbered-list.js +0 -85
- package/dist/docx/blockRangeMarkers.d.ts +0 -36
- package/dist/docx/blockRangeMarkers.js +0 -59
- package/dist/docx/bookmarkPlacement.d.ts +0 -9
- package/dist/docx/bookmarkPlacement.js +0 -50
- package/dist/fonts/embeddedFontTable.d.ts +0 -45
- package/dist/fonts/embeddedFontTable.js +0 -80
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +0 -13
- package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +0 -39
- package/dist/prosemirror/yjsParagraphSourceContract.d.ts +0 -9
- package/dist/prosemirror/yjsParagraphSourceContract.js +0 -26
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { patchBreaksCommentRangeBalance } from "./commentRangeIntegrity.js";
|
|
2
|
+
import { resolveParagraphIdentities } from "./paraIdAttribute.js";
|
|
1
3
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
2
4
|
import { WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, findAttributeByNamespaceUri, getAttributeByNamespaceUri, getChildElements, getLocalName, getNamespacePrefix, getNamespaceUri, parseXmlDocument } from "./xmlParser.js";
|
|
3
5
|
//#region src/docx/selectiveXmlPatch.ts
|
|
@@ -94,24 +96,43 @@ function extractParagraphXml(serializedXml, paraId) {
|
|
|
94
96
|
function buildParagraphOffsetIndex(xml) {
|
|
95
97
|
const seenCount = /* @__PURE__ */ new Map();
|
|
96
98
|
const ranges = /* @__PURE__ */ new Map();
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (
|
|
101
|
-
};
|
|
102
|
-
const noteRange = (paraId, start, end) => {
|
|
103
|
-
if (paraId) ranges.set(paraId, {
|
|
99
|
+
for (const { start, end, paraId } of scanParagraphs(xml)) {
|
|
100
|
+
if (paraId === void 0) continue;
|
|
101
|
+
seenCount.set(paraId, (seenCount.get(paraId) ?? 0) + 1);
|
|
102
|
+
if (end > start) ranges.set(paraId, {
|
|
104
103
|
start,
|
|
105
104
|
end
|
|
106
105
|
});
|
|
107
|
-
}
|
|
106
|
+
}
|
|
107
|
+
const index = /* @__PURE__ */ new Map();
|
|
108
|
+
for (const [id, range] of ranges) if (seenCount.get(id) === 1) index.set(id, range);
|
|
109
|
+
return index;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Every `<w:p>` element of `xml`, in the document order of its opening tags,
|
|
113
|
+
* with the `w14:paraId` that tag carries.
|
|
114
|
+
*
|
|
115
|
+
* Document order is what makes the array an ordinal space: the *n*th entry of
|
|
116
|
+
* the source part and the *n*th entry of the model's serialization name the
|
|
117
|
+
* same paragraph, which is the only way to address a paragraph the producer
|
|
118
|
+
* gave no id. A `<w:p>` nested inside another (inside `mc:AlternateContent`,
|
|
119
|
+
* a text box) is one entry of its own, exactly as
|
|
120
|
+
* {@link countParagraphElements} counts it, so the two never disagree about
|
|
121
|
+
* what an ordinal is. An unterminated paragraph keeps `end === start`: it
|
|
122
|
+
* occupies its ordinal but no splice can be built from it.
|
|
123
|
+
*/
|
|
124
|
+
function scanParagraphs(xml) {
|
|
125
|
+
const paragraphs = [];
|
|
126
|
+
const open = [];
|
|
127
|
+
let pos = 0;
|
|
108
128
|
while (pos < xml.length) {
|
|
109
129
|
const tagStart = xml.indexOf("<", pos);
|
|
110
130
|
if (tagStart === -1) break;
|
|
111
131
|
if (xml.startsWith("</w:p>", tagStart)) {
|
|
112
|
-
const
|
|
132
|
+
const slot = open.pop();
|
|
113
133
|
const end = tagStart + 6;
|
|
114
|
-
|
|
134
|
+
const paragraph = slot === void 0 ? void 0 : paragraphs[slot];
|
|
135
|
+
if (paragraph) paragraph.end = end;
|
|
115
136
|
pos = end;
|
|
116
137
|
continue;
|
|
117
138
|
}
|
|
@@ -122,18 +143,23 @@ function buildParagraphOffsetIndex(xml) {
|
|
|
122
143
|
const tagEnd = xml.indexOf(">", tagStart);
|
|
123
144
|
if (tagEnd === -1) break;
|
|
124
145
|
const openTag = xml.slice(tagStart, tagEnd + 1);
|
|
125
|
-
const paraId = /\bw14:paraId="(?<id>[^"]
|
|
126
|
-
|
|
127
|
-
if (xml[tagEnd - 1] === "/") noteRange(paraId, tagStart, tagEnd + 1);
|
|
128
|
-
else stack.push({
|
|
146
|
+
const paraId = /\bw14:paraId="(?<id>[^"]+)"/u.exec(openTag)?.groups?.["id"];
|
|
147
|
+
if (xml[tagEnd - 1] === "/") paragraphs.push({
|
|
129
148
|
start: tagStart,
|
|
149
|
+
end: tagEnd + 1,
|
|
130
150
|
paraId
|
|
131
151
|
});
|
|
152
|
+
else {
|
|
153
|
+
open.push(paragraphs.length);
|
|
154
|
+
paragraphs.push({
|
|
155
|
+
start: tagStart,
|
|
156
|
+
end: tagStart,
|
|
157
|
+
paraId
|
|
158
|
+
});
|
|
159
|
+
}
|
|
132
160
|
pos = tagEnd + 1;
|
|
133
161
|
}
|
|
134
|
-
|
|
135
|
-
for (const [id, range] of ranges) if (seenCount.get(id) === 1) index.set(id, range);
|
|
136
|
-
return index;
|
|
162
|
+
return paragraphs;
|
|
137
163
|
}
|
|
138
164
|
/**
|
|
139
165
|
* Count <w:p> elements in an XML string (top-level paragraph count).
|
|
@@ -162,40 +188,140 @@ function collectParaIds(xml) {
|
|
|
162
188
|
}
|
|
163
189
|
return ids;
|
|
164
190
|
}
|
|
191
|
+
/** Paragraph ids folio writes and this module may have to remove again. */
|
|
192
|
+
const MINTED_PARA_ID_ATTRIBUTE = /\sw14:(?:para|text)Id="[^"]*"/gu;
|
|
165
193
|
/**
|
|
166
|
-
*
|
|
194
|
+
* The replacement for a paragraph whose source open tag carries no paraId.
|
|
167
195
|
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* -
|
|
196
|
+
* The model always has a key, because folio mints one for every paragraph that
|
|
197
|
+
* arrives without one, and the serializer writes whatever key the model holds.
|
|
198
|
+
* Writing a minted key into the package would upgrade a producer's id-less
|
|
199
|
+
* document to a partly-id'd one on any edit, declare a `w14` namespace the
|
|
200
|
+
* part never had, and turn an id the minter itself calls positional into an
|
|
201
|
+
* authored one the next reader trusts. So the save keeps the author's
|
|
202
|
+
* convention: `ensureParaIds` is the one pass that gives a package ids, and it
|
|
203
|
+
* runs when a host asks for it. An id the source *does* carry (a `w14:textId`
|
|
204
|
+
* beside no paraId) is the author's and stays.
|
|
172
205
|
*/
|
|
173
|
-
|
|
174
|
-
|
|
206
|
+
const withoutMintedIds = (paragraphXml, sourceOpenTag) => {
|
|
207
|
+
const tagEnd = paragraphXml.indexOf(">");
|
|
208
|
+
if (tagEnd === -1) return paragraphXml;
|
|
209
|
+
return paragraphXml.slice(0, tagEnd + 1).replace(MINTED_PARA_ID_ATTRIBUTE, (attribute) => sourceOpenTag.includes(attribute.trim()) ? attribute : "") + paragraphXml.slice(tagEnd + 1);
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Route every changed paragraph from the model's serialization to its region
|
|
213
|
+
* of the source part.
|
|
214
|
+
*
|
|
215
|
+
* One owner for the question the patch turns on: *which paragraph of the file
|
|
216
|
+
* is this model paragraph?* {@link resolveParagraphIdentities} answers it per
|
|
217
|
+
* paragraph, and the union is consumed exhaustively here, so a paragraph the
|
|
218
|
+
* source names by id keeps the id lookup — robust to any reordering — and one
|
|
219
|
+
* the source never named falls back to its ordinal, which is sound exactly
|
|
220
|
+
* when the identity plan says the two sequences line up. A package with ids on
|
|
221
|
+
* some paragraphs and not others therefore needs no special case: its authored
|
|
222
|
+
* ids are the witnesses that prove the ordinals for the rest.
|
|
223
|
+
*/
|
|
224
|
+
const routeChangedParagraphs = (originalXml, serializedXml, changedIds) => {
|
|
225
|
+
const original = scanParagraphs(originalXml);
|
|
226
|
+
const serialized = scanParagraphs(serializedXml);
|
|
227
|
+
const { identities, ordinalsAligned } = resolveParagraphIdentities({
|
|
228
|
+
sourceParaIds: original.map(({ paraId }) => paraId),
|
|
229
|
+
serializedParaIds: serialized.map(({ paraId }) => paraId)
|
|
230
|
+
});
|
|
175
231
|
const originalParaIds = collectParaIds(originalXml);
|
|
176
232
|
const serializedParaIds = collectParaIds(serializedXml);
|
|
233
|
+
const identityByParaId = /* @__PURE__ */ new Map();
|
|
234
|
+
for (const identity of identities) if (identity.type !== "anonymous" && serializedParaIds.get(identity.paraId) === 1) identityByParaId.set(identity.paraId, identity);
|
|
235
|
+
const splices = [];
|
|
177
236
|
for (const id of changedIds) {
|
|
178
|
-
const
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
reason: `paraId-not-found-in-original: ${id}`
|
|
182
|
-
};
|
|
183
|
-
if (origCount > 1) return {
|
|
184
|
-
safe: false,
|
|
237
|
+
const originalCount = originalParaIds.get(id) ?? 0;
|
|
238
|
+
if (originalCount > 1) return {
|
|
239
|
+
type: "refused",
|
|
185
240
|
reason: `duplicate-paraId-in-original: ${id}`
|
|
186
241
|
};
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (serCount === 0) return {
|
|
191
|
-
safe: false,
|
|
242
|
+
const serializedCount = serializedParaIds.get(id) ?? 0;
|
|
243
|
+
if (originalCount === 1 && serializedCount === 0) return {
|
|
244
|
+
type: "refused",
|
|
192
245
|
reason: `paraId-not-found-in-serialized: ${id}`
|
|
193
246
|
};
|
|
194
|
-
if (
|
|
195
|
-
|
|
247
|
+
if (serializedCount === 0) return {
|
|
248
|
+
type: "refused",
|
|
249
|
+
reason: `paraId-not-found-in-original: ${id}`
|
|
250
|
+
};
|
|
251
|
+
if (serializedCount > 1) return {
|
|
252
|
+
type: "refused",
|
|
196
253
|
reason: `duplicate-paraId-in-serialized: ${id}`
|
|
197
254
|
};
|
|
255
|
+
const identity = identityByParaId.get(id);
|
|
256
|
+
if (!identity) return {
|
|
257
|
+
type: "refused",
|
|
258
|
+
reason: `paraId-not-found-in-serialized: ${id}`
|
|
259
|
+
};
|
|
260
|
+
const replacement = serialized[identity.ordinal];
|
|
261
|
+
if (!replacement || replacement.end <= replacement.start) return {
|
|
262
|
+
type: "refused",
|
|
263
|
+
reason: `unterminated-paragraph: ${id}`
|
|
264
|
+
};
|
|
265
|
+
const newXml = serializedXml.slice(replacement.start, replacement.end);
|
|
266
|
+
switch (identity.type) {
|
|
267
|
+
case "authored": {
|
|
268
|
+
const offsets = findParagraphOffsets(originalXml, identity.paraId);
|
|
269
|
+
if (!offsets) return {
|
|
270
|
+
type: "refused",
|
|
271
|
+
reason: `paraId-not-found-in-original: ${id}`
|
|
272
|
+
};
|
|
273
|
+
splices.push({
|
|
274
|
+
start: offsets.start,
|
|
275
|
+
end: offsets.end,
|
|
276
|
+
newXml
|
|
277
|
+
});
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
case "minted": {
|
|
281
|
+
if (!ordinalsAligned) return {
|
|
282
|
+
type: "refused",
|
|
283
|
+
reason: `unaligned-paragraph-ordinals: ${id}`
|
|
284
|
+
};
|
|
285
|
+
const source = original[identity.ordinal];
|
|
286
|
+
if (!source || source.end <= source.start) return {
|
|
287
|
+
type: "refused",
|
|
288
|
+
reason: `paraId-not-found-in-original: ${id}`
|
|
289
|
+
};
|
|
290
|
+
splices.push({
|
|
291
|
+
start: source.start,
|
|
292
|
+
end: source.end,
|
|
293
|
+
newXml: withoutMintedIds(newXml, originalXml.slice(source.start, source.end))
|
|
294
|
+
});
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
case "anonymous": return {
|
|
298
|
+
type: "refused",
|
|
299
|
+
reason: `paraId-not-found-in-serialized: ${id}`
|
|
300
|
+
};
|
|
301
|
+
default: return identity;
|
|
302
|
+
}
|
|
198
303
|
}
|
|
304
|
+
return {
|
|
305
|
+
type: "routed",
|
|
306
|
+
splices
|
|
307
|
+
};
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Validate that a selective patch can be safely applied.
|
|
311
|
+
*
|
|
312
|
+
* Checks:
|
|
313
|
+
* - Every changed paraId routes to one region of the original XML, by its
|
|
314
|
+
* authored id or, when the producer wrote none, by its paragraph ordinal
|
|
315
|
+
* - All changed paraIds exist in serialized XML (exactly once)
|
|
316
|
+
* - Paragraph count matches between original and serialized (unless disabled)
|
|
317
|
+
*/
|
|
318
|
+
function validatePatchSafety(originalXml, serializedXml, changedIds, options = {}) {
|
|
319
|
+
if (changedIds.size === 0) return { safe: true };
|
|
320
|
+
const routing = routeChangedParagraphs(originalXml, serializedXml, changedIds);
|
|
321
|
+
if (routing.type === "refused") return {
|
|
322
|
+
safe: false,
|
|
323
|
+
reason: routing.reason
|
|
324
|
+
};
|
|
199
325
|
if (options.checkParagraphCount === false) return { safe: true };
|
|
200
326
|
const originalCount = countParagraphElements(originalXml);
|
|
201
327
|
const serializedCount = countParagraphElements(serializedXml);
|
|
@@ -237,28 +363,31 @@ function buildPatchedNoteXml(originalXml, serializedXml, changedIds) {
|
|
|
237
363
|
return spliceChangedParagraphs(originalXml, serializedXml, changedIds);
|
|
238
364
|
}
|
|
239
365
|
/**
|
|
366
|
+
* Apply `splices` to `xml`, end-to-start so earlier offsets stay valid.
|
|
367
|
+
*
|
|
368
|
+
* Every selective patch is a splice, and every splice goes through here, so
|
|
369
|
+
* the refusal below is a property of the operation rather than a check each
|
|
370
|
+
* site has to remember. A patch rewrites the regions an edit touched and keeps
|
|
371
|
+
* the rest of the part byte-for-byte, so it can write half a comment range:
|
|
372
|
+
* invalid OOXML that anchors the comment to nothing. Answers null when it
|
|
373
|
+
* would, leaving the caller to rewrite a wider region — ultimately the whole
|
|
374
|
+
* part from the model, which is balanced with itself.
|
|
375
|
+
*/
|
|
376
|
+
const spliceXml = (xml, splices) => {
|
|
377
|
+
let result = xml;
|
|
378
|
+
for (const { start, end, newXml } of [...splices].toSorted((a, b) => b.start - a.start)) result = result.slice(0, start) + newXml + result.slice(end);
|
|
379
|
+
return patchBreaksCommentRangeBalance(xml, result) ? null : result;
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
240
382
|
* Replace each changed paragraph in `originalXml` with its re-serialized form
|
|
241
|
-
* extracted from `serializedXml
|
|
242
|
-
*
|
|
243
|
-
*
|
|
383
|
+
* extracted from `serializedXml`. Assumes safety has already been validated.
|
|
384
|
+
* Returns null if an offset or extraction unexpectedly fails, or if
|
|
385
|
+
* {@link spliceXml} refuses the result; the caller then falls back to a full
|
|
386
|
+
* repack, whose parts are all re-serialized from one model.
|
|
244
387
|
*/
|
|
245
388
|
function spliceChangedParagraphs(originalXml, serializedXml, changedIds) {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
const origOffsets = findParagraphOffsets(originalXml, paraId);
|
|
249
|
-
if (!origOffsets) return null;
|
|
250
|
-
const newXml = extractParagraphXml(serializedXml, paraId);
|
|
251
|
-
if (!newXml) return null;
|
|
252
|
-
replacements.push({
|
|
253
|
-
start: origOffsets.start,
|
|
254
|
-
end: origOffsets.end,
|
|
255
|
-
newXml
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
replacements.sort((a, b) => b.start - a.start);
|
|
259
|
-
let result = originalXml;
|
|
260
|
-
for (const { start, end, newXml } of replacements) result = result.slice(0, start) + newXml + result.slice(end);
|
|
261
|
-
return result;
|
|
389
|
+
const routing = routeChangedParagraphs(originalXml, serializedXml, changedIds);
|
|
390
|
+
return routing.type === "refused" ? null : spliceXml(originalXml, routing.splices);
|
|
262
391
|
}
|
|
263
392
|
/**
|
|
264
393
|
* Depth-count the end of the element that opens at `start` (an `<openLiteral…>`
|
|
@@ -424,11 +553,6 @@ const collectChangedNoteParaIds = (baselineXml, currentXml) => {
|
|
|
424
553
|
}
|
|
425
554
|
return changed;
|
|
426
555
|
};
|
|
427
|
-
const replaceRanges = (xml, replacements) => {
|
|
428
|
-
let result = xml;
|
|
429
|
-
for (const { start, end, newXml } of [...replacements].toSorted((a, b) => b.start - a.start)) result = result.slice(0, start) + newXml + result.slice(end);
|
|
430
|
-
return result;
|
|
431
|
-
};
|
|
432
556
|
/**
|
|
433
557
|
* Patch an existing note part from its model serialization.
|
|
434
558
|
*
|
|
@@ -440,56 +564,79 @@ const replaceRanges = (xml, replacements) => {
|
|
|
440
564
|
* notes, and unaffected equal-shape paragraphs remain byte-exact.
|
|
441
565
|
* `replacementXml` also supplies synthesized automatic note-reference marks,
|
|
442
566
|
* which the parsed model intentionally omits.
|
|
567
|
+
*
|
|
568
|
+
* A comment can be anchored on a note's own text, so its range spans that
|
|
569
|
+
* note's paragraphs and an edit inside the span moves a range half from one
|
|
570
|
+
* paragraph to another. Replacing only the dirty paragraph then drops the half
|
|
571
|
+
* it held and leaves the other standing, so {@link spliceXml} refuses the
|
|
572
|
+
* result and the changed notes are rewritten whole instead — model content on
|
|
573
|
+
* both sides of the range, with every other note still byte-exact.
|
|
443
574
|
*/
|
|
444
575
|
function buildPatchedNotePartXml({ originalXml, baselineXml, serializedXml, replacementXml, elementName, changedParaIds }) {
|
|
445
576
|
const currentElements = collectNoteElementSyntax(serializedXml, elementName);
|
|
446
577
|
const originalElements = collectNoteElementSyntax(originalXml, elementName);
|
|
447
578
|
const replacementElements = collectNoteElementSyntax(replacementXml, elementName);
|
|
448
579
|
const replacementXmlnsDeclarations = collectXmlnsFromOpeningTag(replacementXml);
|
|
449
|
-
const
|
|
580
|
+
const paragraphSplices = [];
|
|
581
|
+
/** The same edits at note granularity, should the paragraph splices be refused. */
|
|
582
|
+
const noteSplices = [];
|
|
450
583
|
const serializedParaIds = collectParaIds(serializedXml);
|
|
451
584
|
const effectiveChangedParaIds = changedParaIds ?? collectChangedNoteParaIds(baselineXml, serializedXml);
|
|
452
585
|
const unroutedChangedParaIds = new Set([...effectiveChangedParaIds].filter((paraId) => serializedParaIds.has(paraId)));
|
|
453
586
|
for (const [id, currentSyntaxEntries] of currentElements) {
|
|
454
587
|
const originalSyntaxEntries = originalElements.get(id);
|
|
455
588
|
const replacementSyntaxEntries = replacementElements.get(id);
|
|
456
|
-
if (currentSyntaxEntries.length !== 1 || originalSyntaxEntries?.length !== 1 || replacementSyntaxEntries?.length !== 1) return
|
|
589
|
+
if (currentSyntaxEntries.length !== 1 || originalSyntaxEntries?.length !== 1 || replacementSyntaxEntries?.length !== 1) return {
|
|
590
|
+
type: "refused",
|
|
591
|
+
reason: "unroutable-paragraph"
|
|
592
|
+
};
|
|
457
593
|
const currentSyntax = currentSyntaxEntries[0];
|
|
458
594
|
const originalSyntax = originalSyntaxEntries[0];
|
|
459
595
|
const replacementSyntax = replacementSyntaxEntries[0];
|
|
460
|
-
if (!currentSyntax || !originalSyntax || !replacementSyntax) return
|
|
596
|
+
if (!currentSyntax || !originalSyntax || !replacementSyntax) return {
|
|
597
|
+
type: "refused",
|
|
598
|
+
reason: "unroutable-paragraph"
|
|
599
|
+
};
|
|
461
600
|
const currentNote = extractNoteElement(serializedXml, currentSyntax, id);
|
|
462
601
|
const originalOffsets = findNoteElement(originalXml, originalSyntax, id);
|
|
463
602
|
const replacementNote = extractNoteElement(replacementXml, replacementSyntax, id);
|
|
464
|
-
if (!currentNote || !originalOffsets || !replacementNote) return
|
|
603
|
+
if (!currentNote || !originalOffsets || !replacementNote) return {
|
|
604
|
+
type: "refused",
|
|
605
|
+
reason: "unroutable-paragraph"
|
|
606
|
+
};
|
|
465
607
|
const originalNote = originalXml.slice(originalOffsets.start, originalOffsets.end);
|
|
466
608
|
const currentParagraphs = paragraphRanges(currentNote, currentSyntax.elementPrefix);
|
|
467
609
|
const originalParagraphs = paragraphRanges(originalNote, originalSyntax.elementPrefix);
|
|
468
610
|
const replacementParagraphs = paragraphRanges(replacementNote, replacementSyntax.elementPrefix);
|
|
469
611
|
const noteChangedParaIds = [...collectParaIds(currentNote).keys()].filter((paraId) => unroutedChangedParaIds.has(paraId));
|
|
470
612
|
if (noteChangedParaIds.length === 0) continue;
|
|
613
|
+
const wholeNoteSplice = {
|
|
614
|
+
start: originalOffsets.start,
|
|
615
|
+
end: originalOffsets.end,
|
|
616
|
+
newXml: rewriteWordprocessingPrefixes(replacementNote, {
|
|
617
|
+
source: replacementSyntax,
|
|
618
|
+
target: originalSyntax,
|
|
619
|
+
sourceXmlnsDeclarations: replacementXmlnsDeclarations
|
|
620
|
+
})
|
|
621
|
+
};
|
|
622
|
+
noteSplices.push(wholeNoteSplice);
|
|
471
623
|
if (currentParagraphs.length !== originalParagraphs.length || currentParagraphs.length !== replacementParagraphs.length) {
|
|
472
624
|
for (const paraId of noteChangedParaIds) unroutedChangedParaIds.delete(paraId);
|
|
473
|
-
|
|
474
|
-
start: originalOffsets.start,
|
|
475
|
-
end: originalOffsets.end,
|
|
476
|
-
newXml: rewriteWordprocessingPrefixes(replacementNote, {
|
|
477
|
-
source: replacementSyntax,
|
|
478
|
-
target: originalSyntax,
|
|
479
|
-
sourceXmlnsDeclarations: replacementXmlnsDeclarations
|
|
480
|
-
})
|
|
481
|
-
});
|
|
625
|
+
paragraphSplices.push(wholeNoteSplice);
|
|
482
626
|
continue;
|
|
483
627
|
}
|
|
484
628
|
for (let index = 0; index < currentParagraphs.length; index++) {
|
|
485
629
|
const currentRange = currentParagraphs[index];
|
|
486
630
|
const originalRange = originalParagraphs[index];
|
|
487
631
|
const replacementRange = replacementParagraphs[index];
|
|
488
|
-
if (!currentRange || !originalRange || !replacementRange) return
|
|
632
|
+
if (!currentRange || !originalRange || !replacementRange) return {
|
|
633
|
+
type: "refused",
|
|
634
|
+
reason: "unroutable-paragraph"
|
|
635
|
+
};
|
|
489
636
|
const routedIds = [...collectParaIds(currentNote.slice(currentRange.start, currentRange.end)).keys()].filter((paraId) => unroutedChangedParaIds.has(paraId));
|
|
490
637
|
if (routedIds.length === 0) continue;
|
|
491
638
|
for (const paraId of routedIds) unroutedChangedParaIds.delete(paraId);
|
|
492
|
-
|
|
639
|
+
paragraphSplices.push({
|
|
493
640
|
start: originalOffsets.start + originalRange.start,
|
|
494
641
|
end: originalOffsets.start + originalRange.end,
|
|
495
642
|
newXml: rewriteWordprocessingPrefixes(replacementNote.slice(replacementRange.start, replacementRange.end), {
|
|
@@ -500,8 +647,23 @@ function buildPatchedNotePartXml({ originalXml, baselineXml, serializedXml, repl
|
|
|
500
647
|
});
|
|
501
648
|
}
|
|
502
649
|
}
|
|
503
|
-
if (unroutedChangedParaIds.size > 0) return
|
|
504
|
-
|
|
650
|
+
if (unroutedChangedParaIds.size > 0) return {
|
|
651
|
+
type: "refused",
|
|
652
|
+
reason: "unroutable-paragraph"
|
|
653
|
+
};
|
|
654
|
+
const patched = spliceXml(originalXml, paragraphSplices);
|
|
655
|
+
if (patched !== null) return {
|
|
656
|
+
type: "patched",
|
|
657
|
+
xml: patched
|
|
658
|
+
};
|
|
659
|
+
const wholeNotes = spliceXml(originalXml, noteSplices);
|
|
660
|
+
return wholeNotes === null ? {
|
|
661
|
+
type: "refused",
|
|
662
|
+
reason: "comment-range-balance"
|
|
663
|
+
} : {
|
|
664
|
+
type: "patched",
|
|
665
|
+
xml: wholeNotes
|
|
666
|
+
};
|
|
505
667
|
}
|
|
506
668
|
/**
|
|
507
669
|
* The full range of the first `<openLiteral …>…</closeTag>` element, or null.
|
|
@@ -568,7 +730,7 @@ function buildNumberingElementOffsetIndex(xml, kind) {
|
|
|
568
730
|
}
|
|
569
731
|
return index;
|
|
570
732
|
}
|
|
571
|
-
const
|
|
733
|
+
const CUSTOM_NUM_FMT_PATTERN = /<w:numFmt w:val="custom"(?: w:format="(?<format>[^"]*)")?\/>/u;
|
|
572
734
|
/**
|
|
573
735
|
* The numbering definitions whose current serialization differs from the
|
|
574
736
|
* baseline (re-parsed original) serialization — the ones actually edited. An id
|
|
@@ -605,30 +767,15 @@ function extractLevelNumFmtElement(levelXml) {
|
|
|
605
767
|
return match ? match[0] : null;
|
|
606
768
|
}
|
|
607
769
|
/**
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
* changed definition never emits a non-OOXML synthetic value.
|
|
770
|
+
* The `@w:format` an original level's number-format element declares, or null
|
|
771
|
+
* when it declares no custom format at all. Telling a preserved format from an
|
|
772
|
+
* edited one is what keeps a genuine change from being reverted.
|
|
612
773
|
*/
|
|
613
|
-
function
|
|
614
|
-
return `<w:numFmt w:val="custom" w:format="${`${"0".repeat(Number.parseInt(width, 10) - 1)}1`}"/>`;
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* The synthetic `decimalZero{width}` width the parser would derive from an
|
|
618
|
-
* original level's number-format element (its custom `w:format` first token),
|
|
619
|
-
* as the same digit-count string the SYNTHETIC_NUM_FMT_PATTERN captures. Mirrors
|
|
620
|
-
* `parseCustomNumberFormat` (first comma-separated token, `^0+1$`, clamped to 5).
|
|
621
|
-
* Returns null when the element carries no zero-padded custom format, so a
|
|
622
|
-
* genuine format change is never mistaken for the original.
|
|
623
|
-
*/
|
|
624
|
-
function originalNumFmtWidth(numFmtElement) {
|
|
774
|
+
function originalCustomNumFmtFormat(numFmtElement) {
|
|
625
775
|
for (const match of numFmtElement.matchAll(/<w:numFmt\b[^>]*\/>/gu)) {
|
|
626
776
|
const tag = match[0];
|
|
627
777
|
if (!/\bw:val="custom"/u.test(tag)) continue;
|
|
628
|
-
|
|
629
|
-
if (format === void 0) continue;
|
|
630
|
-
const firstToken = format.split(",")[0]?.trim() ?? "";
|
|
631
|
-
return /^0+1$/u.test(firstToken) ? String(Math.min(firstToken.length, 5)) : null;
|
|
778
|
+
return /\bw:format="(?<format>[^"]*)"/u.exec(tag)?.groups?.["format"] ?? null;
|
|
632
779
|
}
|
|
633
780
|
return null;
|
|
634
781
|
}
|
|
@@ -661,21 +808,19 @@ function withXmlnsDeclarations(fragmentXml, xmlnsDecls) {
|
|
|
661
808
|
return fragmentXml.slice(0, nameEnd) + additions.join("") + fragmentXml.slice(nameEnd);
|
|
662
809
|
}
|
|
663
810
|
/**
|
|
664
|
-
* Swap each
|
|
665
|
-
*
|
|
811
|
+
* Swap each re-serialized custom numFmt back to the original level's
|
|
812
|
+
* number-format element.
|
|
666
813
|
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
*
|
|
670
|
-
*
|
|
671
|
-
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
677
|
-
* format for the CURRENT width instead — honoring the edit and never leaving a
|
|
678
|
-
* synthetic value.
|
|
814
|
+
* The model holds a custom format as `custom` plus its `@w:format`, which the
|
|
815
|
+
* serializer re-emits as a bare `<w:numFmt w:val="custom" w:format="…"/>`. That
|
|
816
|
+
* is valid OOXML and reparses to the same model, but it is not what the source
|
|
817
|
+
* wrote: Word wraps a custom format in an `mc:AlternateContent` whose Fallback
|
|
818
|
+
* carries a plain format for pre-w14 readers, and the model has no field for
|
|
819
|
+
* the Fallback. When an unrelated field of the definition is edited the whole
|
|
820
|
+
* definition is re-serialized, so without this pass that wrapper would be
|
|
821
|
+
* flattened away. Restore it by ilvl only when the model's format still matches
|
|
822
|
+
* the original's; a level whose format was actually edited keeps the model's
|
|
823
|
+
* own element, which is the edit.
|
|
679
824
|
*/
|
|
680
825
|
function restoreLevelNumFmts(originalDefXml, currentDefXml) {
|
|
681
826
|
const replacements = [];
|
|
@@ -684,28 +829,29 @@ function restoreLevelNumFmts(originalDefXml, currentDefXml) {
|
|
|
684
829
|
const curOffsets = findElementByIdAttr(currentDefXml, LEVEL_OPEN_LITERAL, LEVEL_CLOSE_TAG, LEVEL_ID_ATTR, ilvl);
|
|
685
830
|
if (!curOffsets) continue;
|
|
686
831
|
const curLevel = currentDefXml.slice(curOffsets.start, curOffsets.end);
|
|
687
|
-
const
|
|
688
|
-
if (!
|
|
832
|
+
const custom = CUSTOM_NUM_FMT_PATTERN.exec(curLevel);
|
|
833
|
+
if (!custom) continue;
|
|
689
834
|
const origLevel = extractElementByIdAttr(originalDefXml, LEVEL_OPEN_LITERAL, LEVEL_CLOSE_TAG, LEVEL_ID_ATTR, ilvl);
|
|
690
|
-
const
|
|
835
|
+
const currentFormat = custom.groups?.["format"] ?? null;
|
|
691
836
|
const original = origLevel ? extractLevelNumFmtElement(origLevel) : null;
|
|
692
|
-
|
|
693
|
-
|
|
837
|
+
if (!original || !origLevel || originalCustomNumFmtFormat(original) !== currentFormat) continue;
|
|
838
|
+
const ancestorXmlns = {
|
|
694
839
|
...collectXmlnsFromOpeningTag(originalDefXml),
|
|
695
840
|
...collectXmlnsFromOpeningTag(origLevel)
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
|
|
841
|
+
};
|
|
842
|
+
const restoredLevel = spliceXml(curLevel, [{
|
|
843
|
+
start: custom.index,
|
|
844
|
+
end: custom.index + custom[0].length,
|
|
845
|
+
newXml: withXmlnsDeclarations(original, ancestorXmlns)
|
|
846
|
+
}]);
|
|
847
|
+
if (restoredLevel === null) continue;
|
|
699
848
|
replacements.push({
|
|
700
849
|
start: curOffsets.start,
|
|
701
850
|
end: curOffsets.end,
|
|
702
851
|
newXml: restoredLevel
|
|
703
852
|
});
|
|
704
853
|
}
|
|
705
|
-
|
|
706
|
-
let result = currentDefXml;
|
|
707
|
-
for (const { start, end, newXml } of replacements) result = result.slice(0, start) + newXml + result.slice(end);
|
|
708
|
-
return result;
|
|
854
|
+
return spliceXml(currentDefXml, replacements) ?? currentDefXml;
|
|
709
855
|
}
|
|
710
856
|
/**
|
|
711
857
|
* Build a patched `word/numbering.xml` by splicing the changed `w:abstractNum` /
|
|
@@ -733,10 +879,7 @@ function buildPatchedNumberingXml(originalXml, currentXml, changed) {
|
|
|
733
879
|
return true;
|
|
734
880
|
};
|
|
735
881
|
if (!collect("abstractNum", changed.abstractNums) || !collect("num", changed.nums)) return null;
|
|
736
|
-
|
|
737
|
-
let result = originalXml;
|
|
738
|
-
for (const { start, end, newXml } of replacements) result = result.slice(0, start) + newXml + result.slice(end);
|
|
739
|
-
return result;
|
|
882
|
+
return spliceXml(originalXml, replacements);
|
|
740
883
|
}
|
|
741
884
|
/**
|
|
742
885
|
* Numbering definitions present in `currentXml` (the model's serialization)
|
|
@@ -851,12 +994,12 @@ function appendNumberingDefs(xml, currentXml, added) {
|
|
|
851
994
|
return head + abstractXmls.join("") + middle + numXmls.join("") + tail;
|
|
852
995
|
}
|
|
853
996
|
/**
|
|
854
|
-
* For an added abstract definition that
|
|
997
|
+
* For an added abstract definition that carries a flattened custom numFmt, find
|
|
855
998
|
* the original abstract it was cloned from (same serialized body apart from the
|
|
856
999
|
* id) and restore the level formats from it.
|
|
857
1000
|
*/
|
|
858
1001
|
function restoreClonedLevelNumFmts(originalXml, currentXml, addedDefXml, addedId) {
|
|
859
|
-
if (!
|
|
1002
|
+
if (!CUSTOM_NUM_FMT_PATTERN.test(addedDefXml)) return addedDefXml;
|
|
860
1003
|
const addedBody = stripAbstractNumId(addedDefXml, addedId);
|
|
861
1004
|
const originalIds = collectElementIds(originalXml, NUMBERING_OPEN_LITERAL.abstractNum, NUMBERING_ID_ATTR.abstractNum);
|
|
862
1005
|
for (const [id] of originalIds) {
|
|
@@ -872,4 +1015,4 @@ function escapeRegExp(str) {
|
|
|
872
1015
|
return str.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
873
1016
|
}
|
|
874
1017
|
//#endregion
|
|
875
|
-
export { appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, validatePatchSafety };
|
|
1018
|
+
export { appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, scanParagraphs, spliceXml, validatePatchSafety };
|