@stll/folio-core 0.46.0 → 0.47.1
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.d.ts +17 -1
- package/dist/ai-edits/apply.js +31 -27
- package/dist/ai-edits/headless.d.ts +9 -2
- package/dist/ai-edits/headless.js +5 -3
- 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 -1
- package/dist/compare/content-alignment.js +192 -46
- 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/section-boundary-properties.js +1 -2
- package/dist/content-controls/checkboxDisplay.d.ts +8 -2
- package/dist/content-controls/checkboxDisplay.js +11 -5
- package/dist/content-controls/mutateContentControls.js +41 -42
- package/dist/controller/layoutPipeline.js +8 -3
- package/dist/display-list/build/buildDisplayList.js +7 -7
- package/dist/display-list/build/imagePrimitives.d.ts +4 -4
- package/dist/display-list/build/imagePrimitives.js +38 -20
- package/dist/display-list/build/pageBorderPrimitives.js +2 -1
- package/dist/display-list/build/paragraphPrimitives.js +93 -13
- 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 +1 -19
- package/dist/display-list/primitives.d.ts +13 -2
- package/dist/display-list/primitives.js +36 -1
- package/dist/document-operations.d.ts +9 -2
- package/dist/document-operations.js +5 -3
- package/dist/docx/attributeRemainder.d.ts +34 -1
- package/dist/docx/attributeRemainder.js +49 -3
- package/dist/docx/blockContentParser.d.ts +2 -0
- package/dist/docx/blockContentParser.js +39 -67
- package/dist/docx/blockPlainText.js +3 -1
- 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.js +1 -1
- package/dist/docx/commentParser.js +3 -3
- package/dist/docx/commentRangeIntegrity.js +1 -1
- package/dist/docx/commentRangeJoin.js +1 -1
- package/dist/docx/commentReferenceNormalization.js +3 -2
- package/dist/docx/commentReplyMarkers.js +1 -1
- package/dist/docx/compatibility.js +56 -42
- package/dist/docx/containerChildren.d.ts +110 -13
- package/dist/docx/containerChildren.gen.d.ts +16 -1
- package/dist/docx/containerChildren.gen.js +18 -1
- package/dist/docx/containerChildren.js +63 -13
- package/dist/docx/diagramPreview.d.ts +14 -2
- package/dist/docx/diagramPreview.js +81 -169
- package/dist/docx/documentParser.js +4 -1
- 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/fontTableParser.js +102 -41
- package/dist/docx/footnoteParser.js +10 -6
- package/dist/docx/groupDrawingParser.js +4 -3
- package/dist/docx/headerFooterReferenceNormalization.js +1 -1
- package/dist/docx/hyperlinkParser.d.ts +45 -7
- package/dist/docx/hyperlinkParser.js +126 -57
- package/dist/docx/imageParser.js +127 -107
- 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 +84 -3
- package/dist/docx/inlineWrapperContent.js +85 -4
- 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 +4 -2
- 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 +91 -1
- package/dist/docx/paraIdAttribute.js +79 -1
- package/dist/docx/paragraphParser.d.ts +9 -24
- package/dist/docx/paragraphParser.js +212 -396
- package/dist/docx/paragraphProperties.d.ts +23 -0
- package/dist/docx/paragraphProperties.js +279 -0
- package/dist/docx/paragraphPropertySource.js +2 -0
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +2 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +14 -7
- package/dist/docx/paragraphTraversal.d.ts +14 -10
- package/dist/docx/paragraphTraversal.js +47 -49
- package/dist/docx/parseWarningMessage.js +3 -0
- package/dist/docx/parserEnums.d.ts +6 -8
- package/dist/docx/parserEnums.js +4 -6
- package/dist/docx/preservedRunContent.js +16 -6
- 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 +2 -2
- package/dist/docx/rezip.d.ts +28 -2
- package/dist/docx/rezip.js +78 -9
- package/dist/docx/runConsolidator.d.ts +42 -2
- package/dist/docx/runConsolidator.js +60 -6
- package/dist/docx/runParser.d.ts +54 -18
- package/dist/docx/runParser.js +379 -295
- 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 +236 -240
- package/dist/docx/selectiveSave.js +3 -2
- package/dist/docx/selectiveXmlPatch.d.ts +21 -2
- package/dist/docx/selectiveXmlPatch.js +195 -99
- package/dist/docx/serializer/blockSdtSerializer.js +2 -96
- package/dist/docx/serializer/borderSerializer.d.ts +5 -5
- package/dist/docx/serializer/borderSerializer.js +10 -8
- package/dist/docx/serializer/documentSerializer.js +3 -0
- package/dist/docx/serializer/fontTableSerializer.js +31 -3
- package/dist/docx/serializer/headerFooterSerializer.js +3 -0
- package/dist/docx/serializer/markupRangeAttributes.d.ts +9 -1
- package/dist/docx/serializer/markupRangeAttributes.js +9 -1
- package/dist/docx/serializer/noteSerializer.js +3 -0
- 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 +88 -188
- package/dist/docx/serializer/runSerializer.d.ts +1 -5
- package/dist/docx/serializer/runSerializer.js +109 -59
- package/dist/docx/serializer/sdtPropertiesSerializer.d.ts +26 -0
- package/dist/docx/serializer/sdtPropertiesSerializer.js +111 -0
- package/dist/docx/serializer/sectionPropertiesSerializer.js +34 -45
- package/dist/docx/serializer/settingsSerializer.js +6 -4
- package/dist/docx/serializer/stylesSerializer.js +8 -11
- package/dist/docx/serializer/tableSerializer.js +268 -100
- 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 +18 -16
- package/dist/docx/server/migrateYjsAttrSchema.js +3 -3
- 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 +8 -3
- 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 +10 -1
- package/dist/docx/tableParser.js +505 -181
- package/dist/docx/textBoxParser.d.ts +3 -1
- package/dist/docx/textBoxParser.js +18 -8
- 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/vmlImageParser.d.ts +13 -4
- package/dist/docx/vmlImageParser.js +74 -31
- 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/xmlParser.d.ts +14 -1
- package/dist/docx/xmlParser.js +18 -2
- package/dist/fonts/embeddedFonts.js +3 -3
- package/dist/headless-layout.js +2 -0
- 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/internal/headlessRevisionResolution.js +9 -0
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +3 -1
- 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 +177 -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/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 +47 -17
- package/dist/layout-engine/types.js +16 -1
- package/dist/layout-painter/borderStroke.d.ts +18 -4
- package/dist/layout-painter/renderPage.js +6 -4
- package/dist/layout-painter/renderParagraph.d.ts +2 -1
- package/dist/layout-painter/renderParagraph.js +13 -26
- 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/markdown/renderBlock.js +3 -1
- package/dist/markdown/renderRuns.js +7 -2
- package/dist/markdown/renderTable.js +2 -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/prosemirror/attrs/index.d.ts +22 -4
- package/dist/prosemirror/attrs/index.js +498 -60
- 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 +24 -19
- package/dist/prosemirror/commands/image.d.ts +1 -1
- package/dist/prosemirror/commands/image.js +4 -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/conversion/fromProseDoc.d.ts +18 -2
- package/dist/prosemirror/conversion/fromProseDoc.js +330 -183
- 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.js +371 -141
- package/dist/prosemirror/emptyRangeAnchor.d.ts +53 -0
- package/dist/prosemirror/emptyRangeAnchor.js +158 -0
- package/dist/prosemirror/extensions/StarterKit.js +8 -2
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +19 -15
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -2
- package/dist/prosemirror/extensions/features/ListExtension.js +43 -24
- 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 +26 -2
- package/dist/prosemirror/extensions/markRegistry.js +73 -10
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +17 -3
- 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.js +2 -1
- 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.js +10 -0
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +8 -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/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 +4 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +141 -123
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +4 -0
- 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.js +20 -3
- 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/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 +1 -1
- package/dist/prosemirror/replacedAnnotations.js +24 -6
- package/dist/prosemirror/revisionCarriers.d.ts +86 -2
- package/dist/prosemirror/revisionCarriers.js +86 -60
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -0
- package/dist/prosemirror/runFormattingInlineCarriers.js +2 -0
- 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 +2 -2
- package/dist/prosemirror/schema/marks.d.ts +23 -4
- package/dist/prosemirror/schema/nodes.d.ts +220 -24
- 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 +2 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
- package/dist/prosemirror/utils/extractTrackedChanges.d.ts +10 -11
- package/dist/prosemirror/utils/extractTrackedChanges.js +109 -92
- package/dist/prosemirror/validation.js +17 -6
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +2 -2
- package/dist/prosemirror/yjsDocumentMetadata.js +428 -7
- package/dist/prosemirror/zeroWidthAnchors.js +4 -0
- 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/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/mergeDocumentContent.js +5 -3
- package/dist/utils/paragraphFormattingMerge.js +27 -6
- package/dist/utils/replaceText.js +1 -1
- 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/bookmarkPlacement.d.ts +0 -9
- package/dist/docx/bookmarkPlacement.js +0 -52
- 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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { patchBreaksCommentRangeBalance } from "./commentRangeIntegrity.js";
|
|
2
|
+
import { resolveParagraphIdentities } from "./paraIdAttribute.js";
|
|
2
3
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
3
4
|
import { WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, findAttributeByNamespaceUri, getAttributeByNamespaceUri, getChildElements, getLocalName, getNamespacePrefix, getNamespaceUri, parseXmlDocument } from "./xmlParser.js";
|
|
4
5
|
//#region src/docx/selectiveXmlPatch.ts
|
|
@@ -95,24 +96,43 @@ function extractParagraphXml(serializedXml, paraId) {
|
|
|
95
96
|
function buildParagraphOffsetIndex(xml) {
|
|
96
97
|
const seenCount = /* @__PURE__ */ new Map();
|
|
97
98
|
const ranges = /* @__PURE__ */ new Map();
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
};
|
|
103
|
-
const noteRange = (paraId, start, end) => {
|
|
104
|
-
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, {
|
|
105
103
|
start,
|
|
106
104
|
end
|
|
107
105
|
});
|
|
108
|
-
}
|
|
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;
|
|
109
128
|
while (pos < xml.length) {
|
|
110
129
|
const tagStart = xml.indexOf("<", pos);
|
|
111
130
|
if (tagStart === -1) break;
|
|
112
131
|
if (xml.startsWith("</w:p>", tagStart)) {
|
|
113
|
-
const
|
|
132
|
+
const slot = open.pop();
|
|
114
133
|
const end = tagStart + 6;
|
|
115
|
-
|
|
134
|
+
const paragraph = slot === void 0 ? void 0 : paragraphs[slot];
|
|
135
|
+
if (paragraph) paragraph.end = end;
|
|
116
136
|
pos = end;
|
|
117
137
|
continue;
|
|
118
138
|
}
|
|
@@ -123,18 +143,23 @@ function buildParagraphOffsetIndex(xml) {
|
|
|
123
143
|
const tagEnd = xml.indexOf(">", tagStart);
|
|
124
144
|
if (tagEnd === -1) break;
|
|
125
145
|
const openTag = xml.slice(tagStart, tagEnd + 1);
|
|
126
|
-
const paraId = /\bw14:paraId="(?<id>[^"]
|
|
127
|
-
|
|
128
|
-
if (xml[tagEnd - 1] === "/") noteRange(paraId, tagStart, tagEnd + 1);
|
|
129
|
-
else stack.push({
|
|
146
|
+
const paraId = /\bw14:paraId="(?<id>[^"]+)"/u.exec(openTag)?.groups?.["id"];
|
|
147
|
+
if (xml[tagEnd - 1] === "/") paragraphs.push({
|
|
130
148
|
start: tagStart,
|
|
149
|
+
end: tagEnd + 1,
|
|
131
150
|
paraId
|
|
132
151
|
});
|
|
152
|
+
else {
|
|
153
|
+
open.push(paragraphs.length);
|
|
154
|
+
paragraphs.push({
|
|
155
|
+
start: tagStart,
|
|
156
|
+
end: tagStart,
|
|
157
|
+
paraId
|
|
158
|
+
});
|
|
159
|
+
}
|
|
133
160
|
pos = tagEnd + 1;
|
|
134
161
|
}
|
|
135
|
-
|
|
136
|
-
for (const [id, range] of ranges) if (seenCount.get(id) === 1) index.set(id, range);
|
|
137
|
-
return index;
|
|
162
|
+
return paragraphs;
|
|
138
163
|
}
|
|
139
164
|
/**
|
|
140
165
|
* Count <w:p> elements in an XML string (top-level paragraph count).
|
|
@@ -163,40 +188,140 @@ function collectParaIds(xml) {
|
|
|
163
188
|
}
|
|
164
189
|
return ids;
|
|
165
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;
|
|
166
193
|
/**
|
|
167
|
-
*
|
|
194
|
+
* The replacement for a paragraph whose source open tag carries no paraId.
|
|
168
195
|
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* -
|
|
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.
|
|
173
205
|
*/
|
|
174
|
-
|
|
175
|
-
|
|
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
|
+
});
|
|
176
231
|
const originalParaIds = collectParaIds(originalXml);
|
|
177
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 = [];
|
|
178
236
|
for (const id of changedIds) {
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
reason: `paraId-not-found-in-original: ${id}`
|
|
183
|
-
};
|
|
184
|
-
if (origCount > 1) return {
|
|
185
|
-
safe: false,
|
|
237
|
+
const originalCount = originalParaIds.get(id) ?? 0;
|
|
238
|
+
if (originalCount > 1) return {
|
|
239
|
+
type: "refused",
|
|
186
240
|
reason: `duplicate-paraId-in-original: ${id}`
|
|
187
241
|
};
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (serCount === 0) return {
|
|
192
|
-
safe: false,
|
|
242
|
+
const serializedCount = serializedParaIds.get(id) ?? 0;
|
|
243
|
+
if (originalCount === 1 && serializedCount === 0) return {
|
|
244
|
+
type: "refused",
|
|
193
245
|
reason: `paraId-not-found-in-serialized: ${id}`
|
|
194
246
|
};
|
|
195
|
-
if (
|
|
196
|
-
|
|
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",
|
|
197
253
|
reason: `duplicate-paraId-in-serialized: ${id}`
|
|
198
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
|
+
}
|
|
199
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
|
+
};
|
|
200
325
|
if (options.checkParagraphCount === false) return { safe: true };
|
|
201
326
|
const originalCount = countParagraphElements(originalXml);
|
|
202
327
|
const serializedCount = countParagraphElements(serializedXml);
|
|
@@ -261,19 +386,8 @@ const spliceXml = (xml, splices) => {
|
|
|
261
386
|
* repack, whose parts are all re-serialized from one model.
|
|
262
387
|
*/
|
|
263
388
|
function spliceChangedParagraphs(originalXml, serializedXml, changedIds) {
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
const origOffsets = findParagraphOffsets(originalXml, paraId);
|
|
267
|
-
if (!origOffsets) return null;
|
|
268
|
-
const newXml = extractParagraphXml(serializedXml, paraId);
|
|
269
|
-
if (!newXml) return null;
|
|
270
|
-
replacements.push({
|
|
271
|
-
start: origOffsets.start,
|
|
272
|
-
end: origOffsets.end,
|
|
273
|
-
newXml
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
return spliceXml(originalXml, replacements);
|
|
389
|
+
const routing = routeChangedParagraphs(originalXml, serializedXml, changedIds);
|
|
390
|
+
return routing.type === "refused" ? null : spliceXml(originalXml, routing.splices);
|
|
277
391
|
}
|
|
278
392
|
/**
|
|
279
393
|
* Depth-count the end of the element that opens at `start` (an `<openLiteral…>`
|
|
@@ -616,7 +730,7 @@ function buildNumberingElementOffsetIndex(xml, kind) {
|
|
|
616
730
|
}
|
|
617
731
|
return index;
|
|
618
732
|
}
|
|
619
|
-
const
|
|
733
|
+
const CUSTOM_NUM_FMT_PATTERN = /<w:numFmt w:val="custom"(?: w:format="(?<format>[^"]*)")?\/>/u;
|
|
620
734
|
/**
|
|
621
735
|
* The numbering definitions whose current serialization differs from the
|
|
622
736
|
* baseline (re-parsed original) serialization — the ones actually edited. An id
|
|
@@ -653,30 +767,15 @@ function extractLevelNumFmtElement(levelXml) {
|
|
|
653
767
|
return match ? match[0] : null;
|
|
654
768
|
}
|
|
655
769
|
/**
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
* 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.
|
|
660
773
|
*/
|
|
661
|
-
function
|
|
662
|
-
return `<w:numFmt w:val="custom" w:format="${`${"0".repeat(Number.parseInt(width, 10) - 1)}1`}"/>`;
|
|
663
|
-
}
|
|
664
|
-
/**
|
|
665
|
-
* The synthetic `decimalZero{width}` width the parser would derive from an
|
|
666
|
-
* original level's number-format element (its custom `w:format` first token),
|
|
667
|
-
* as the same digit-count string the SYNTHETIC_NUM_FMT_PATTERN captures. Mirrors
|
|
668
|
-
* `parseCustomNumberFormat` (first comma-separated token, `^0+1$`, clamped to 5).
|
|
669
|
-
* Returns null when the element carries no zero-padded custom format, so a
|
|
670
|
-
* genuine format change is never mistaken for the original.
|
|
671
|
-
*/
|
|
672
|
-
function originalNumFmtWidth(numFmtElement) {
|
|
774
|
+
function originalCustomNumFmtFormat(numFmtElement) {
|
|
673
775
|
for (const match of numFmtElement.matchAll(/<w:numFmt\b[^>]*\/>/gu)) {
|
|
674
776
|
const tag = match[0];
|
|
675
777
|
if (!/\bw:val="custom"/u.test(tag)) continue;
|
|
676
|
-
|
|
677
|
-
if (format === void 0) continue;
|
|
678
|
-
const firstToken = format.split(",")[0]?.trim() ?? "";
|
|
679
|
-
return /^0+1$/u.test(firstToken) ? String(Math.min(firstToken.length, 5)) : null;
|
|
778
|
+
return /\bw:format="(?<format>[^"]*)"/u.exec(tag)?.groups?.["format"] ?? null;
|
|
680
779
|
}
|
|
681
780
|
return null;
|
|
682
781
|
}
|
|
@@ -709,21 +808,19 @@ function withXmlnsDeclarations(fragmentXml, xmlnsDecls) {
|
|
|
709
808
|
return fragmentXml.slice(0, nameEnd) + additions.join("") + fragmentXml.slice(nameEnd);
|
|
710
809
|
}
|
|
711
810
|
/**
|
|
712
|
-
* Swap each
|
|
713
|
-
*
|
|
811
|
+
* Swap each re-serialized custom numFmt back to the original level's
|
|
812
|
+
* number-format element.
|
|
714
813
|
*
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
*
|
|
721
|
-
*
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
* format for the CURRENT width instead — honoring the edit and never leaving a
|
|
726
|
-
* 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.
|
|
727
824
|
*/
|
|
728
825
|
function restoreLevelNumFmts(originalDefXml, currentDefXml) {
|
|
729
826
|
const replacements = [];
|
|
@@ -732,21 +829,20 @@ function restoreLevelNumFmts(originalDefXml, currentDefXml) {
|
|
|
732
829
|
const curOffsets = findElementByIdAttr(currentDefXml, LEVEL_OPEN_LITERAL, LEVEL_CLOSE_TAG, LEVEL_ID_ATTR, ilvl);
|
|
733
830
|
if (!curOffsets) continue;
|
|
734
831
|
const curLevel = currentDefXml.slice(curOffsets.start, curOffsets.end);
|
|
735
|
-
const
|
|
736
|
-
if (!
|
|
832
|
+
const custom = CUSTOM_NUM_FMT_PATTERN.exec(curLevel);
|
|
833
|
+
if (!custom) continue;
|
|
737
834
|
const origLevel = extractElementByIdAttr(originalDefXml, LEVEL_OPEN_LITERAL, LEVEL_CLOSE_TAG, LEVEL_ID_ATTR, ilvl);
|
|
738
|
-
const
|
|
835
|
+
const currentFormat = custom.groups?.["format"] ?? null;
|
|
739
836
|
const original = origLevel ? extractLevelNumFmtElement(origLevel) : null;
|
|
740
|
-
|
|
741
|
-
|
|
837
|
+
if (!original || !origLevel || originalCustomNumFmtFormat(original) !== currentFormat) continue;
|
|
838
|
+
const ancestorXmlns = {
|
|
742
839
|
...collectXmlnsFromOpeningTag(originalDefXml),
|
|
743
840
|
...collectXmlnsFromOpeningTag(origLevel)
|
|
744
|
-
}
|
|
745
|
-
else replacement = reconstructCustomNumFmt(currentWidth);
|
|
841
|
+
};
|
|
746
842
|
const restoredLevel = spliceXml(curLevel, [{
|
|
747
|
-
start:
|
|
748
|
-
end:
|
|
749
|
-
newXml:
|
|
843
|
+
start: custom.index,
|
|
844
|
+
end: custom.index + custom[0].length,
|
|
845
|
+
newXml: withXmlnsDeclarations(original, ancestorXmlns)
|
|
750
846
|
}]);
|
|
751
847
|
if (restoredLevel === null) continue;
|
|
752
848
|
replacements.push({
|
|
@@ -898,12 +994,12 @@ function appendNumberingDefs(xml, currentXml, added) {
|
|
|
898
994
|
return head + abstractXmls.join("") + middle + numXmls.join("") + tail;
|
|
899
995
|
}
|
|
900
996
|
/**
|
|
901
|
-
* For an added abstract definition that
|
|
997
|
+
* For an added abstract definition that carries a flattened custom numFmt, find
|
|
902
998
|
* the original abstract it was cloned from (same serialized body apart from the
|
|
903
999
|
* id) and restore the level formats from it.
|
|
904
1000
|
*/
|
|
905
1001
|
function restoreClonedLevelNumFmts(originalXml, currentXml, addedDefXml, addedId) {
|
|
906
|
-
if (!
|
|
1002
|
+
if (!CUSTOM_NUM_FMT_PATTERN.test(addedDefXml)) return addedDefXml;
|
|
907
1003
|
const addedBody = stripAbstractNumId(addedDefXml, addedId);
|
|
908
1004
|
const originalIds = collectElementIds(originalXml, NUMBERING_OPEN_LITERAL.abstractNum, NUMBERING_ID_ATTR.abstractNum);
|
|
909
1005
|
for (const [id] of originalIds) {
|
|
@@ -919,4 +1015,4 @@ function escapeRegExp(str) {
|
|
|
919
1015
|
return str.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
920
1016
|
}
|
|
921
1017
|
//#endregion
|
|
922
|
-
export { appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, spliceXml, validatePatchSafety };
|
|
1018
|
+
export { appendNumberingDefs, buildParagraphOffsetIndex, buildPatchedDocumentXml, buildPatchedNotePartXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectAddedNumberingDefs, collectChangedNoteParaIds, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, patchNumberingDefinitions, scanParagraphs, spliceXml, validatePatchSafety };
|
|
@@ -1,102 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isSingleWellFormedElement } from "./xmlUtils.js";
|
|
3
|
-
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
1
|
+
import { serializeSdtWrapper } from "./sdtPropertiesSerializer.js";
|
|
4
2
|
//#region src/docx/serializer/blockSdtSerializer.ts
|
|
5
|
-
/**
|
|
6
|
-
* Block-level SDT serializer.
|
|
7
|
-
*
|
|
8
|
-
* Replays `<w:sdtPr>` (and `<w:sdtEndPr>` when present) verbatim from the
|
|
9
|
-
* `rawPropertiesXml` / `rawEndPropertiesXml` strings captured by the parser.
|
|
10
|
-
* That keeps OOXML element order intact (`CT_SdtPr` is an `xsd:sequence`,
|
|
11
|
-
* ECMA-376 §17.5.2) and round-trips unmodeled features — `w:dataBinding`,
|
|
12
|
-
* `w15:repeatingSection`, `@lastValue`, custom XML mappings — without us
|
|
13
|
-
* having to enumerate them.
|
|
14
|
-
*
|
|
15
|
-
* If a `BlockSdt` was constructed programmatically (no parsed snapshot to
|
|
16
|
-
* replay), fall back to a minimal projection from the modeled fields so the
|
|
17
|
-
* result is still a valid `<w:sdt>`.
|
|
18
|
-
*
|
|
19
|
-
* Sharing the helper between the document body and the header/footer
|
|
20
|
-
* serializers keeps body↔HF parity in one place.
|
|
21
|
-
*/
|
|
22
|
-
function serializeFallbackSdtPr(props) {
|
|
23
|
-
const parts = [];
|
|
24
|
-
if (props.id !== void 0) parts.push(`<w:id w:val="${props.id}"/>`);
|
|
25
|
-
if (props.alias) parts.push(`<w:alias w:val="${escapeXmlAttribute(props.alias)}"/>`);
|
|
26
|
-
if (props.tag) parts.push(`<w:tag w:val="${escapeXmlAttribute(props.tag)}"/>`);
|
|
27
|
-
if (props.lock) parts.push(`<w:lock w:val="${props.lock}"/>`);
|
|
28
|
-
if (props.placeholder) parts.push(`<w:placeholder><w:docPart w:val="${escapeXmlAttribute(props.placeholder)}"/></w:placeholder>`);
|
|
29
|
-
if (props.showingPlaceholder) parts.push("<w:showingPlcHdr/>");
|
|
30
|
-
switch (props.sdtType) {
|
|
31
|
-
case "plainText":
|
|
32
|
-
parts.push("<w:text/>");
|
|
33
|
-
break;
|
|
34
|
-
case "date": {
|
|
35
|
-
const fullDateAttr = props.dateValueISO ? ` w:fullDate="${escapeXmlAttribute(props.dateValueISO)}"` : "";
|
|
36
|
-
const formatChild = props.dateFormat ? `<w:dateFormat w:val="${escapeXmlAttribute(props.dateFormat)}"/>` : "";
|
|
37
|
-
if (fullDateAttr || formatChild) parts.push(`<w:date${fullDateAttr}>${formatChild}</w:date>`);
|
|
38
|
-
else parts.push("<w:date/>");
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
case "dropdown":
|
|
42
|
-
case "comboBox": {
|
|
43
|
-
const tag = props.sdtType === "dropdown" ? "w:dropDownList" : "w:comboBox";
|
|
44
|
-
const items = (props.listItems ?? []).map((item) => `<w:listItem w:displayText="${escapeXmlAttribute(item.displayText)}" w:value="${escapeXmlAttribute(item.value)}"/>`).join("");
|
|
45
|
-
parts.push(`<${tag}>${items}</${tag}>`);
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
case "checkbox": {
|
|
49
|
-
const val = props.checked ? "1" : "0";
|
|
50
|
-
parts.push(`<w14:checkbox><w14:checked w14:val="${val}"/></w14:checkbox>`);
|
|
51
|
-
break;
|
|
52
|
-
}
|
|
53
|
-
case "picture":
|
|
54
|
-
parts.push("<w:picture/>");
|
|
55
|
-
break;
|
|
56
|
-
case "buildingBlockGallery":
|
|
57
|
-
parts.push("<w:docPartObj/>");
|
|
58
|
-
break;
|
|
59
|
-
case "group":
|
|
60
|
-
parts.push("<w:group/>");
|
|
61
|
-
break;
|
|
62
|
-
default: break;
|
|
63
|
-
}
|
|
64
|
-
return `<w:sdtPr>${parts.join("")}</w:sdtPr>`;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* `properties.dropdownLastValue` is the only record of what was selected.
|
|
68
|
-
*
|
|
69
|
-
* The XSD default of `@w:lastValue` is the empty string, so "never selected",
|
|
70
|
-
* "cleared" and "selected" are three distinguishable states, and the body's
|
|
71
|
-
* display text is evidence for none of them: it is equally the placeholder of
|
|
72
|
-
* a dropdown nobody has touched, and a displayText shared by two list items
|
|
73
|
-
* picks the wrong sibling. The parser records the authored `@w:lastValue` and
|
|
74
|
-
* `setContentControlValue` records a pick; what neither wrote is no selection.
|
|
75
|
-
*
|
|
76
|
-
* `""` is a value a producer can author (`<w:listItem w:value=""/>`), so
|
|
77
|
-
* presence is the test, not truthiness.
|
|
78
|
-
*/
|
|
79
|
-
function extractDropdownLastValue(blockSdt) {
|
|
80
|
-
if (blockSdt.properties.sdtType !== "dropdown" && blockSdt.properties.sdtType !== "comboBox") return;
|
|
81
|
-
return blockSdt.properties.dropdownLastValue;
|
|
82
|
-
}
|
|
83
|
-
function extractDateFullDate(blockSdt) {
|
|
84
|
-
if (blockSdt.properties.sdtType !== "date") return;
|
|
85
|
-
const iso = blockSdt.properties.dateValueISO;
|
|
86
|
-
return iso !== void 0 && iso.length > 0 ? iso : void 0;
|
|
87
|
-
}
|
|
88
3
|
function serializeBlockSdt(blockSdt, serializeChild) {
|
|
89
4
|
const props = blockSdt.properties;
|
|
90
|
-
|
|
91
|
-
const dateFullDate = extractDateFullDate(blockSdt);
|
|
92
|
-
const dropdownLastValue = extractDropdownLastValue(blockSdt);
|
|
93
|
-
const sdtPrXml = reconcileRawSdtPr(baseSdtPr, props, {
|
|
94
|
-
...dateFullDate !== void 0 ? { dateFullDate } : {},
|
|
95
|
-
...dropdownLastValue !== void 0 ? { dropdownLastValue } : {}
|
|
96
|
-
});
|
|
97
|
-
const sdtEndPrXml = props.rawEndPropertiesXml && isSingleWellFormedElement(props.rawEndPropertiesXml, "sdtEndPr") ? props.rawEndPropertiesXml : "";
|
|
98
|
-
const contentXml = blockSdt.content.map(serializeChild).join("");
|
|
99
|
-
return `<w:sdt>${sdtPrXml}${sdtEndPrXml}${props.rawSdtChildrenBeforeContent ?? ""}<w:sdtContent>${contentXml}</w:sdtContent>${props.rawSdtChildrenAfterContent ?? ""}</w:sdt>`;
|
|
5
|
+
return serializeSdtWrapper(props, blockSdt.content.map(serializeChild).join(""));
|
|
100
6
|
}
|
|
101
7
|
//#endregion
|
|
102
8
|
export { serializeBlockSdt };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { document_d_exports } from "../../types/document.js";
|
|
2
2
|
//#region src/docx/serializer/borderSerializer.d.ts
|
|
3
|
-
type ClassifiedBorderField = "style" | "color" | "size" | "space" | "shadow" | "frame" | "artRelationshipId" | "topLeftArtRelationshipId" | "topRightArtRelationshipId" | "bottomLeftArtRelationshipId" | "bottomRightArtRelationshipId";
|
|
3
|
+
type ClassifiedBorderField = "style" | "color" | "size" | "space" | "shadow" | "frame" | "artRelationshipId" | "topLeftArtRelationshipId" | "topRightArtRelationshipId" | "bottomLeftArtRelationshipId" | "bottomRightArtRelationshipId" | "preservedAttributes";
|
|
4
4
|
type ExhaustiveBorder = document_d_exports.ExhaustiveFields<document_d_exports.BorderSpec, ClassifiedBorderField>;
|
|
5
5
|
/**
|
|
6
6
|
* Serialize a single border element (`<w:top .../>`, `<w:left .../>`, ...).
|
|
@@ -16,10 +16,10 @@ type ExhaustiveBorder = document_d_exports.ExhaustiveFields<document_d_exports.B
|
|
|
16
16
|
* turned-off side; those are emitted when present so the value survives a
|
|
17
17
|
* save→parse round-trip and is not otherwise added.
|
|
18
18
|
*
|
|
19
|
-
* `
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* An unrecognised `w:val` and the color values come straight from the parsed
|
|
20
|
+
* DOCX, so they are untrusted and are `escapeXmlAttribute`'d before re-entering
|
|
21
|
+
* XML attributes; for valid documents these are enum/hex values, so escaping is
|
|
22
|
+
* a no-op.
|
|
23
23
|
*/
|
|
24
24
|
declare function serializeBorder(input: ExhaustiveBorder | undefined, elementName: string): string;
|
|
25
25
|
//#endregion
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { serializePreservedAttributes } from "../attributeRemainder.js";
|
|
1
2
|
import { intAttr } from "./xmlUtils.js";
|
|
2
3
|
import { escapeXmlAttribute } from "@stll/docx-core";
|
|
4
|
+
import { borderStyleToken, themeColorToken } from "@stll/docx-core/model";
|
|
3
5
|
//#region src/docx/serializer/borderSerializer.ts
|
|
4
6
|
/**
|
|
5
7
|
* Serialize a single border element (`<w:top .../>`, `<w:left .../>`, ...).
|
|
@@ -15,22 +17,22 @@ import { escapeXmlAttribute } from "@stll/docx-core";
|
|
|
15
17
|
* turned-off side; those are emitted when present so the value survives a
|
|
16
18
|
* save→parse round-trip and is not otherwise added.
|
|
17
19
|
*
|
|
18
|
-
* `
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
20
|
+
* An unrecognised `w:val` and the color values come straight from the parsed
|
|
21
|
+
* DOCX, so they are untrusted and are `escapeXmlAttribute`'d before re-entering
|
|
22
|
+
* XML attributes; for valid documents these are enum/hex values, so escaping is
|
|
23
|
+
* a no-op.
|
|
22
24
|
*/
|
|
23
25
|
function serializeBorder(input, elementName) {
|
|
24
26
|
if (!input) return "";
|
|
25
|
-
const { style, color, size, space, shadow, frame, artRelationshipId, topLeftArtRelationshipId, topRightArtRelationshipId, bottomLeftArtRelationshipId, bottomRightArtRelationshipId } = input;
|
|
26
|
-
const attrs = [`w:val="${escapeXmlAttribute(style)}"`];
|
|
27
|
+
const { style, color, size, space, shadow, frame, artRelationshipId, topLeftArtRelationshipId, topRightArtRelationshipId, bottomLeftArtRelationshipId, bottomRightArtRelationshipId, preservedAttributes } = input;
|
|
28
|
+
const attrs = [`w:val="${escapeXmlAttribute(borderStyleToken(style))}"`];
|
|
27
29
|
if (size !== void 0) attrs.push(`w:sz="${intAttr(size)}"`);
|
|
28
30
|
if (space !== void 0) attrs.push(`w:space="${intAttr(space)}"`);
|
|
29
31
|
if (color) {
|
|
30
32
|
const { auto, rgb, themeColor, themeTint, themeShade } = color;
|
|
31
33
|
if (auto) attrs.push("w:color=\"auto\"");
|
|
32
34
|
else if (rgb) attrs.push(`w:color="${escapeXmlAttribute(rgb)}"`);
|
|
33
|
-
if (themeColor) attrs.push(`w:themeColor="${escapeXmlAttribute(themeColor)}"`);
|
|
35
|
+
if (themeColor) attrs.push(`w:themeColor="${escapeXmlAttribute(themeColorToken(themeColor))}"`);
|
|
34
36
|
if (themeTint) attrs.push(`w:themeTint="${escapeXmlAttribute(themeTint)}"`);
|
|
35
37
|
if (themeShade) attrs.push(`w:themeShade="${escapeXmlAttribute(themeShade)}"`);
|
|
36
38
|
}
|
|
@@ -41,7 +43,7 @@ function serializeBorder(input, elementName) {
|
|
|
41
43
|
if (topRightArtRelationshipId) attrs.push(`r:topRight="${escapeXmlAttribute(topRightArtRelationshipId)}"`);
|
|
42
44
|
if (bottomLeftArtRelationshipId) attrs.push(`r:bottomLeft="${escapeXmlAttribute(bottomLeftArtRelationshipId)}"`);
|
|
43
45
|
if (bottomRightArtRelationshipId) attrs.push(`r:bottomRight="${escapeXmlAttribute(bottomRightArtRelationshipId)}"`);
|
|
44
|
-
return `<w:${elementName} ${attrs.join(" ")}/>`;
|
|
46
|
+
return `<w:${elementName} ${serializePreservedAttributes(attrs, preservedAttributes).join(" ")}/>`;
|
|
45
47
|
}
|
|
46
48
|
//#endregion
|
|
47
49
|
export { serializeBorder };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
2
|
+
import { serializeBookmarkMarker } from "./markupRangeAttributes.js";
|
|
2
3
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
4
|
import { serializePartElement } from "./partNamespaces.js";
|
|
4
5
|
import { resetAutoIdCounter } from "./runSerializer.js";
|
|
@@ -43,6 +44,8 @@ function serializeBlockContent(block) {
|
|
|
43
44
|
case "table": return serializeTable(block, serializeParagraph);
|
|
44
45
|
case "blockSdt": return serializeBlockSdt(block, serializeBlockContent);
|
|
45
46
|
case "preservedBlock": return block.xml;
|
|
47
|
+
case "bookmarkStart":
|
|
48
|
+
case "bookmarkEnd": return serializeBookmarkMarker(block);
|
|
46
49
|
default: return block;
|
|
47
50
|
}
|
|
48
51
|
}
|