@stll/folio-core 0.0.1-placeholder.0 → 0.1.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/LICENSE +202 -0
- package/NOTICE.md +29 -0
- package/README.md +41 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/ai-edits/apply.d.ts +35 -0
- package/dist/ai-edits/apply.js +683 -0
- package/dist/ai-edits/clean-text.d.ts +28 -0
- package/dist/ai-edits/clean-text.js +23 -0
- package/dist/ai-edits/headless.d.ts +225 -0
- package/dist/ai-edits/headless.js +513 -0
- package/dist/ai-edits/index.d.ts +6 -0
- package/dist/ai-edits/index.js +5 -0
- package/dist/ai-edits/inline-emphasis.d.ts +38 -0
- package/dist/ai-edits/inline-emphasis.js +78 -0
- package/dist/ai-edits/snapshot.d.ts +9 -0
- package/dist/ai-edits/snapshot.js +195 -0
- package/dist/ai-edits/types.d.ts +156 -0
- package/dist/ai-edits/types.js +0 -0
- package/dist/ai-edits/word-diff.d.ts +20 -0
- package/dist/ai-edits/word-diff.js +77 -0
- package/dist/ai-suggestions/apply.d.ts +17 -0
- package/dist/ai-suggestions/apply.js +64 -0
- package/dist/ai-suggestions/conflict.d.ts +22 -0
- package/dist/ai-suggestions/conflict.js +67 -0
- package/dist/ai-suggestions/text-positions.d.ts +21 -0
- package/dist/ai-suggestions/text-positions.js +48 -0
- package/dist/ai-suggestions/types.d.ts +199 -0
- package/dist/ai-suggestions/types.js +59 -0
- package/dist/content-controls/errors.d.ts +52 -0
- package/dist/content-controls/errors.js +36 -0
- package/dist/content-controls/findContentControls.d.ts +55 -0
- package/dist/content-controls/findContentControls.js +75 -0
- package/dist/content-controls/index.d.ts +4 -0
- package/dist/content-controls/index.js +4 -0
- package/dist/content-controls/mutateContentControls.d.ts +51 -0
- package/dist/content-controls/mutateContentControls.js +377 -0
- package/dist/controller/folioEditor.d.ts +21 -0
- package/dist/controller/folioEditor.js +29 -0
- package/dist/controller/folioEditorEvents.d.ts +23 -0
- package/dist/controller/folioEditorEvents.js +24 -0
- package/dist/controller/hiddenEditorApi.d.ts +35 -0
- package/dist/controller/hiddenEditorApi.js +112 -0
- package/dist/controller/hiddenEditorManager.d.ts +93 -0
- package/dist/controller/hiddenEditorManager.js +308 -0
- package/dist/controller/layoutPipeline.d.ts +63 -0
- package/dist/controller/layoutPipeline.js +406 -0
- package/dist/controller/layoutScheduler.d.ts +41 -0
- package/dist/controller/layoutScheduler.js +59 -0
- package/dist/controller/layoutSession.d.ts +24 -0
- package/dist/controller/layoutSession.js +13 -0
- package/dist/docx/blockContentParser.d.ts +13 -0
- package/dist/docx/blockContentParser.js +289 -0
- package/dist/docx/bookmarkParser.d.ts +178 -0
- package/dist/docx/bookmarkParser.js +246 -0
- package/dist/docx/bookmarkPlacement.d.ts +10 -0
- package/dist/docx/bookmarkPlacement.js +50 -0
- package/dist/docx/bulletMarkers.d.ts +4 -0
- package/dist/docx/bulletMarkers.js +42 -0
- package/dist/docx/commentParser.d.ts +34 -0
- package/dist/docx/commentParser.js +127 -0
- package/dist/docx/commentReferenceNormalization.d.ts +25 -0
- package/dist/docx/commentReferenceNormalization.js +97 -0
- package/dist/docx/commentReplyMarkers.d.ts +20 -0
- package/dist/docx/commentReplyMarkers.js +123 -0
- package/dist/docx/compatibility.d.ts +12 -0
- package/dist/docx/compatibility.js +77 -0
- package/dist/docx/documentParser.d.ts +65 -0
- package/dist/docx/documentParser.js +209 -0
- package/dist/docx/drawingUtils.d.ts +56 -0
- package/dist/docx/drawingUtils.js +305 -0
- package/dist/docx/fieldParser.d.ts +228 -0
- package/dist/docx/fieldParser.js +559 -0
- package/dist/docx/footnoteParser.d.ts +109 -0
- package/dist/docx/footnoteParser.js +270 -0
- package/dist/docx/headerFooterParser.d.ts +119 -0
- package/dist/docx/headerFooterParser.js +266 -0
- package/dist/docx/headerFooterRefParser.d.ts +22 -0
- package/dist/docx/headerFooterRefParser.js +52 -0
- package/dist/docx/headerFooterReferenceNormalization.d.ts +19 -0
- package/dist/docx/headerFooterReferenceNormalization.js +64 -0
- package/dist/docx/hyperlinkParser.d.ts +108 -0
- package/dist/docx/hyperlinkParser.js +230 -0
- package/dist/docx/imageParser.d.ts +93 -0
- package/dist/docx/imageParser.js +522 -0
- package/dist/docx/mathToMathml.d.ts +15 -0
- package/dist/docx/mathToMathml.js +357 -0
- package/dist/docx/modelValidation.d.ts +13 -0
- package/dist/docx/modelValidation.js +21 -0
- package/dist/docx/normalizeBaseDirection.d.ts +12 -0
- package/dist/docx/normalizeBaseDirection.js +81 -0
- package/dist/docx/notePropertiesParser.d.ts +16 -0
- package/dist/docx/notePropertiesParser.js +99 -0
- package/dist/docx/numberingParser.d.ts +86 -0
- package/dist/docx/numberingParser.js +735 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +25 -0
- package/dist/docx/numberingReferenceNormalization.js +22 -0
- package/dist/docx/paragraphParser.d.ts +86 -0
- package/dist/docx/paragraphParser.js +1132 -0
- package/dist/docx/paragraphTraversal.d.ts +19 -0
- package/dist/docx/paragraphTraversal.js +76 -0
- package/dist/docx/parser.d.ts +67 -0
- package/dist/docx/parser.js +391 -0
- package/dist/docx/parserEnums.d.ts +45 -0
- package/dist/docx/parserEnums.js +70 -0
- package/dist/docx/relsParser.d.ts +160 -0
- package/dist/docx/relsParser.js +235 -0
- package/dist/docx/replyToComment.d.ts +29 -0
- package/dist/docx/replyToComment.js +73 -0
- package/dist/docx/rezip.d.ts +166 -0
- package/dist/docx/rezip.js +1194 -0
- package/dist/docx/runConsolidator.d.ts +57 -0
- package/dist/docx/runConsolidator.js +224 -0
- package/dist/docx/runParser.d.ts +78 -0
- package/dist/docx/runParser.js +661 -0
- package/dist/docx/sdtProperties.d.ts +15 -0
- package/dist/docx/sdtProperties.js +290 -0
- package/dist/docx/sdtPropertiesPatch.d.ts +16 -0
- package/dist/docx/sdtPropertiesPatch.js +144 -0
- package/dist/docx/sectionParser.d.ts +95 -0
- package/dist/docx/sectionParser.js +534 -0
- package/dist/docx/selectiveSave.d.ts +25 -0
- package/dist/docx/selectiveSave.js +247 -0
- package/dist/docx/selectiveSaveFlags.d.ts +33 -0
- package/dist/docx/selectiveSaveFlags.js +11 -0
- package/dist/docx/selectiveSaveTripwire.d.ts +33 -0
- package/dist/docx/selectiveSaveTripwire.js +79 -0
- package/dist/docx/selectiveXmlPatch.d.ts +103 -0
- package/dist/docx/selectiveXmlPatch.js +493 -0
- package/dist/docx/serializer/blockSdtSerializer.d.ts +6 -0
- package/dist/docx/serializer/blockSdtSerializer.js +88 -0
- package/dist/docx/serializer/borderSerializer.d.ts +25 -0
- package/dist/docx/serializer/borderSerializer.js +44 -0
- package/dist/docx/serializer/commentSerializer.d.ts +31 -0
- package/dist/docx/serializer/commentSerializer.js +184 -0
- package/dist/docx/serializer/documentSerializer.d.ts +65 -0
- package/dist/docx/serializer/documentSerializer.js +199 -0
- package/dist/docx/serializer/headerFooterSerializer.d.ts +12 -0
- package/dist/docx/serializer/headerFooterSerializer.js +84 -0
- package/dist/docx/serializer/noteSerializer.d.ts +19 -0
- package/dist/docx/serializer/noteSerializer.js +70 -0
- package/dist/docx/serializer/numberingSerializer.d.ts +12 -0
- package/dist/docx/serializer/numberingSerializer.js +93 -0
- package/dist/docx/serializer/paragraphSerializer.d.ts +48 -0
- package/dist/docx/serializer/paragraphSerializer.js +559 -0
- package/dist/docx/serializer/runSerializer.d.ts +56 -0
- package/dist/docx/serializer/runSerializer.js +621 -0
- package/dist/docx/serializer/sectionPropertiesSerializer.d.ts +6 -0
- package/dist/docx/serializer/sectionPropertiesSerializer.js +187 -0
- package/dist/docx/serializer/tableSerializer.d.ts +79 -0
- package/dist/docx/serializer/tableSerializer.js +422 -0
- package/dist/docx/serializer/xmlUtils.d.ts +20 -0
- package/dist/docx/serializer/xmlUtils.js +25 -0
- package/dist/docx/settingsParser.d.ts +8 -0
- package/dist/docx/settingsParser.js +36 -0
- package/dist/docx/shapeParser.d.ts +20 -0
- package/dist/docx/shapeParser.js +272 -0
- package/dist/docx/styleParser.d.ts +50 -0
- package/dist/docx/styleParser.js +905 -0
- package/dist/docx/tableParser.d.ts +202 -0
- package/dist/docx/tableParser.js +811 -0
- package/dist/docx/textBoxParser.d.ts +117 -0
- package/dist/docx/textBoxParser.js +262 -0
- package/dist/docx/themeParser.d.ts +77 -0
- package/dist/docx/themeParser.js +330 -0
- package/dist/docx/trackedMoveRangeNormalization.d.ts +22 -0
- package/dist/docx/trackedMoveRangeNormalization.js +100 -0
- package/dist/docx/unzip.d.ts +118 -0
- package/dist/docx/unzip.js +383 -0
- package/dist/docx/vmlImageParser.d.ts +16 -0
- package/dist/docx/vmlImageParser.js +100 -0
- package/dist/docx/watermarkParser.d.ts +45 -0
- package/dist/docx/watermarkParser.js +348 -0
- package/dist/docx/wrapTypes.d.ts +29 -0
- package/dist/docx/wrapTypes.js +48 -0
- package/dist/docx/xmlParser.d.ts +297 -0
- package/dist/docx/xmlParser.js +527 -0
- package/dist/fields/bookmarkPages.d.ts +13 -0
- package/dist/fields/bookmarkPages.js +66 -0
- package/dist/fields/bookmarkText.d.ts +16 -0
- package/dist/fields/bookmarkText.js +61 -0
- package/dist/fields/evaluateField.d.ts +23 -0
- package/dist/fields/evaluateField.js +77 -0
- package/dist/fields/fieldContext.d.ts +21 -0
- package/dist/fields/fieldContext.js +0 -0
- package/dist/fields/resolveFieldValues.d.ts +44 -0
- package/dist/fields/resolveFieldValues.js +204 -0
- package/dist/fields/sectionPageCounts.d.ts +11 -0
- package/dist/fields/sectionPageCounts.js +16 -0
- package/dist/fields/seqValues.d.ts +14 -0
- package/dist/fields/seqValues.js +36 -0
- package/dist/fonts/embeddedFontTable.d.ts +42 -0
- package/dist/fonts/embeddedFontTable.js +80 -0
- package/dist/fonts/embeddedFonts.d.ts +46 -0
- package/dist/fonts/embeddedFonts.js +112 -0
- package/dist/fonts/fontDeobfuscation.d.ts +30 -0
- package/dist/fonts/fontDeobfuscation.js +57 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +23 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +57 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +316 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +74 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +432 -0
- package/dist/layout-bridge/convert/templatePreviewFlow.d.ts +36 -0
- package/dist/layout-bridge/convert/templatePreviewFlow.js +176 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +65 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +1309 -0
- package/dist/layout-bridge/convert/wrapEditorViewAsSurface.d.ts +17 -0
- package/dist/layout-bridge/convert/wrapEditorViewAsSurface.js +36 -0
- package/dist/layout-bridge/dom/clickToPositionDom.d.ts +66 -0
- package/dist/layout-bridge/dom/clickToPositionDom.js +304 -0
- package/dist/layout-bridge/dom/findBodyPmSpans.d.ts +7 -0
- package/dist/layout-bridge/dom/findBodyPmSpans.js +17 -0
- package/dist/layout-bridge/dom/findHfPmSpans.d.ts +62 -0
- package/dist/layout-bridge/dom/findHfPmSpans.js +197 -0
- package/dist/layout-bridge/engine/clickToPosition.d.ts +66 -0
- package/dist/layout-bridge/engine/clickToPosition.js +403 -0
- package/dist/layout-bridge/engine/hitTest.d.ts +135 -0
- package/dist/layout-bridge/engine/hitTest.js +375 -0
- package/dist/layout-bridge/engine/measuring/index.d.ts +10 -0
- package/dist/layout-bridge/engine/measuring/index.js +9 -0
- package/dist/layout-bridge/engine/selectionRects.d.ts +59 -0
- package/dist/layout-bridge/engine/selectionRects.js +485 -0
- package/dist/layout-bridge/engine/tableWidthUtils.d.ts +7 -0
- package/dist/layout-bridge/engine/tableWidthUtils.js +25 -0
- package/dist/layout-engine/index.d.ts +44 -0
- package/dist/layout-engine/index.js +691 -0
- package/dist/layout-engine/keep-together.d.ts +43 -0
- package/dist/layout-engine/keep-together.js +98 -0
- package/dist/layout-engine/layoutInstrumentation.d.ts +50 -0
- package/dist/layout-engine/layoutInstrumentation.js +43 -0
- package/dist/layout-engine/lineFlow.d.ts +8 -0
- package/dist/layout-engine/lineFlow.js +17 -0
- package/dist/layout-engine/measure/cache.d.ts +93 -0
- package/dist/layout-engine/measure/cache.js +245 -0
- package/dist/layout-engine/measure/clampFloatingWrapMargins.d.ts +20 -0
- package/dist/layout-engine/measure/clampFloatingWrapMargins.js +29 -0
- package/dist/layout-engine/measure/featureFlags.d.ts +44 -0
- package/dist/layout-engine/measure/featureFlags.js +19 -0
- package/dist/layout-engine/measure/floatingZones.d.ts +89 -0
- package/dist/layout-engine/measure/floatingZones.js +152 -0
- package/dist/layout-engine/measure/font-metrics.worker.d.ts +17 -0
- package/dist/layout-engine/measure/font-metrics.worker.js +104 -0
- package/dist/layout-engine/measure/index.d.ts +9 -0
- package/dist/layout-engine/measure/index.js +8 -0
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +40 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +76 -0
- package/dist/layout-engine/measure/measureBlocks.d.ts +25 -0
- package/dist/layout-engine/measure/measureBlocks.js +450 -0
- package/dist/layout-engine/measure/measureContainer.d.ts +24 -0
- package/dist/layout-engine/measure/measureContainer.js +280 -0
- package/dist/layout-engine/measure/measureHelpers.d.ts +82 -0
- package/dist/layout-engine/measure/measureHelpers.js +156 -0
- package/dist/layout-engine/measure/measureParagraph.d.ts +61 -0
- package/dist/layout-engine/measure/measureParagraph.js +724 -0
- package/dist/layout-engine/measure/measureProvider.d.ts +23 -0
- package/dist/layout-engine/measure/measureProvider.js +35 -0
- package/dist/layout-engine/measure/measureTypes.d.ts +61 -0
- package/dist/layout-engine/measure/measureTypes.js +0 -0
- package/dist/layout-engine/measure/measureWorker.d.ts +54 -0
- package/dist/layout-engine/measure/measureWorker.js +249 -0
- package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +88 -0
- package/dist/layout-engine/measure/measureWorkerProtocol.js +20 -0
- package/dist/layout-engine/measure/tableCellFloating.d.ts +26 -0
- package/dist/layout-engine/measure/tableCellFloating.js +99 -0
- package/dist/layout-engine/paginator.d.ts +84 -0
- package/dist/layout-engine/paginator.js +348 -0
- package/dist/layout-engine/paragraphFragmentRange.d.ts +9 -0
- package/dist/layout-engine/paragraphFragmentRange.js +40 -0
- package/dist/layout-engine/section-breaks.d.ts +78 -0
- package/dist/layout-engine/section-breaks.js +182 -0
- package/dist/layout-engine/tableRowBreak.d.ts +23 -0
- package/dist/layout-engine/tableRowBreak.js +147 -0
- package/dist/layout-engine/textBoxFlow.d.ts +50 -0
- package/dist/layout-engine/textBoxFlow.js +160 -0
- package/dist/layout-engine/types.d.ts +1031 -0
- package/dist/layout-engine/types.js +100 -0
- package/dist/layout-painter/documentColors.d.ts +4 -0
- package/dist/layout-painter/documentColors.js +40 -0
- package/dist/layout-painter/index.d.ts +110 -0
- package/dist/layout-painter/index.js +182 -0
- package/dist/layout-painter/registry/modules/image.d.ts +6 -0
- package/dist/layout-painter/registry/modules/image.js +17 -0
- package/dist/layout-painter/registry/modules/paragraph.d.ts +6 -0
- package/dist/layout-painter/registry/modules/paragraph.js +18 -0
- package/dist/layout-painter/registry/modules/table.d.ts +6 -0
- package/dist/layout-painter/registry/modules/table.js +16 -0
- package/dist/layout-painter/registry/modules/textBox.d.ts +6 -0
- package/dist/layout-painter/registry/modules/textBox.js +13 -0
- package/dist/layout-painter/registry/modules.d.ts +6 -0
- package/dist/layout-painter/registry/modules.js +26 -0
- package/dist/layout-painter/registry/registry.d.ts +24 -0
- package/dist/layout-painter/registry/registry.js +53 -0
- package/dist/layout-painter/registry/types.d.ts +61 -0
- package/dist/layout-painter/registry/types.js +0 -0
- package/dist/layout-painter/renderFragment.d.ts +32 -0
- package/dist/layout-painter/renderFragment.js +114 -0
- package/dist/layout-painter/renderImage.d.ts +88 -0
- package/dist/layout-painter/renderImage.js +130 -0
- package/dist/layout-painter/renderPage.d.ts +264 -0
- package/dist/layout-painter/renderPage.js +1795 -0
- package/dist/layout-painter/renderParagraph.d.ts +93 -0
- package/dist/layout-painter/renderParagraph.js +1300 -0
- package/dist/layout-painter/renderTable.d.ts +36 -0
- package/dist/layout-painter/renderTable.js +432 -0
- package/dist/layout-painter/renderTextBox.d.ts +22 -0
- package/dist/layout-painter/renderTextBox.js +67 -0
- package/dist/layout-painter/renderUtils.d.ts +42 -0
- package/dist/layout-painter/renderUtils.js +30 -0
- package/dist/layout-painter/renderWatermark.d.ts +16 -0
- package/dist/layout-painter/renderWatermark.js +61 -0
- package/dist/layout-painter/sdtBoundary.d.ts +6 -0
- package/dist/layout-painter/sdtBoundary.js +28 -0
- package/dist/managers/ContextMenuManager.d.ts +28 -0
- package/dist/managers/ContextMenuManager.js +48 -0
- package/dist/managers/DocumentLoaderManager.d.ts +47 -0
- package/dist/managers/DocumentLoaderManager.js +69 -0
- package/dist/managers/EditorModeManager.d.ts +28 -0
- package/dist/managers/EditorModeManager.js +50 -0
- package/dist/managers/ErrorManager.d.ts +26 -0
- package/dist/managers/ErrorManager.js +85 -0
- package/dist/managers/FindReplaceManager.d.ts +54 -0
- package/dist/managers/FindReplaceManager.js +104 -0
- package/dist/managers/HistoryManager.d.ts +92 -0
- package/dist/managers/HistoryManager.js +193 -0
- package/dist/managers/Subscribable.d.ts +34 -0
- package/dist/managers/Subscribable.js +46 -0
- package/dist/managers/TableSelectionManager.d.ts +74 -0
- package/dist/managers/TableSelectionManager.js +225 -0
- package/dist/managers/editorShortcuts.d.ts +42 -0
- package/dist/managers/editorShortcuts.js +60 -0
- package/dist/managers/types.d.ts +41 -0
- package/dist/managers/types.js +0 -0
- package/dist/markdown/annotations.d.ts +14 -0
- package/dist/markdown/annotations.js +42 -0
- package/dist/markdown/escape.d.ts +36 -0
- package/dist/markdown/escape.js +59 -0
- package/dist/markdown/fromMarkdown.d.ts +11 -0
- package/dist/markdown/fromMarkdown.js +223 -0
- package/dist/markdown/headings.d.ts +13 -0
- package/dist/markdown/headings.js +20 -0
- package/dist/markdown/images.d.ts +13 -0
- package/dist/markdown/images.js +63 -0
- package/dist/markdown/index.d.ts +18 -0
- package/dist/markdown/index.js +33 -0
- package/dist/markdown/internals.d.ts +15 -0
- package/dist/markdown/internals.js +35 -0
- package/dist/markdown/renderBlock.d.ts +7 -0
- package/dist/markdown/renderBlock.js +68 -0
- package/dist/markdown/renderParagraph.d.ts +11 -0
- package/dist/markdown/renderParagraph.js +64 -0
- package/dist/markdown/renderRuns.d.ts +11 -0
- package/dist/markdown/renderRuns.js +265 -0
- package/dist/markdown/renderTable.d.ts +8 -0
- package/dist/markdown/renderTable.js +229 -0
- package/dist/markdown/trailers.d.ts +13 -0
- package/dist/markdown/trailers.js +54 -0
- package/dist/markdown/types.d.ts +118 -0
- package/dist/markdown/types.js +0 -0
- package/dist/model.d.ts +13 -0
- package/dist/model.js +4 -0
- package/dist/paged-layout/LayoutSelectionGate.d.ts +80 -0
- package/dist/paged-layout/LayoutSelectionGate.js +131 -0
- package/dist/paged-layout/headerFooterMargins.d.ts +73 -0
- package/dist/paged-layout/headerFooterMargins.js +120 -0
- package/dist/paged-layout/hiddenEditorScroll.d.ts +4 -0
- package/dist/paged-layout/hiddenEditorScroll.js +4 -0
- package/dist/paged-layout/incrementalMeasure.d.ts +33 -0
- package/dist/paged-layout/incrementalMeasure.js +56 -0
- package/dist/paged-layout/rangeProjection.d.ts +51 -0
- package/dist/paged-layout/rangeProjection.js +153 -0
- package/dist/paged-layout/readOnlyEditAttempt.d.ts +5 -0
- package/dist/paged-layout/readOnlyEditAttempt.js +22 -0
- package/dist/paged-layout/scrollNavigation.d.ts +23 -0
- package/dist/paged-layout/scrollNavigation.js +31 -0
- package/dist/paged-layout/scrollPageInfo.d.ts +41 -0
- package/dist/paged-layout/scrollPageInfo.js +34 -0
- package/dist/paged-layout/scrollToPmPosition.d.ts +17 -0
- package/dist/paged-layout/scrollToPmPosition.js +95 -0
- package/dist/paged-layout/sectionBlockWidths.d.ts +35 -0
- package/dist/paged-layout/sectionBlockWidths.js +52 -0
- package/dist/paged-layout/sectionGeometry.d.ts +21 -0
- package/dist/paged-layout/sectionGeometry.js +36 -0
- package/dist/paged-layout/selectionViewportRect.d.ts +29 -0
- package/dist/paged-layout/selectionViewportRect.js +55 -0
- package/dist/paged-layout/tableColumnResize.d.ts +19 -0
- package/dist/paged-layout/tableColumnResize.js +28 -0
- package/dist/paged-layout/tableInsertButtonGeometry.d.ts +15 -0
- package/dist/paged-layout/tableInsertButtonGeometry.js +15 -0
- package/dist/paged-layout/transactionDirtyRange.d.ts +7 -0
- package/dist/paged-layout/transactionDirtyRange.js +27 -0
- package/dist/paged-layout/zoomScrollAnchor.d.ts +40 -0
- package/dist/paged-layout/zoomScrollAnchor.js +25 -0
- package/dist/prosemirror/attrs/index.d.ts +80 -0
- package/dist/prosemirror/attrs/index.js +1218 -0
- package/dist/prosemirror/autospacingBase.d.ts +11 -0
- package/dist/prosemirror/autospacingBase.js +16 -0
- package/dist/prosemirror/commands/comments.d.ts +93 -0
- package/dist/prosemirror/commands/comments.js +435 -0
- package/dist/prosemirror/commands/contentControls.d.ts +45 -0
- package/dist/prosemirror/commands/contentControls.js +294 -0
- package/dist/prosemirror/commands/contentControlsBlockFill.d.ts +15 -0
- package/dist/prosemirror/commands/contentControlsBlockFill.js +19 -0
- package/dist/prosemirror/commands/formatPainter.d.ts +31 -0
- package/dist/prosemirror/commands/formatPainter.js +130 -0
- package/dist/prosemirror/commands/formatting.d.ts +32 -0
- package/dist/prosemirror/commands/formatting.js +45 -0
- package/dist/prosemirror/commands/hyperlink.d.ts +31 -0
- package/dist/prosemirror/commands/hyperlink.js +79 -0
- package/dist/prosemirror/commands/image.d.ts +59 -0
- package/dist/prosemirror/commands/image.js +219 -0
- package/dist/prosemirror/commands/index.d.ts +13 -0
- package/dist/prosemirror/commands/index.js +13 -0
- package/dist/prosemirror/commands/pageBreak.d.ts +10 -0
- package/dist/prosemirror/commands/pageBreak.js +47 -0
- package/dist/prosemirror/commands/paragraph.d.ts +39 -0
- package/dist/prosemirror/commands/paragraph.js +64 -0
- package/dist/prosemirror/commands/pastePlainText.d.ts +39 -0
- package/dist/prosemirror/commands/pastePlainText.js +67 -0
- package/dist/prosemirror/commands/table.d.ts +83 -0
- package/dist/prosemirror/commands/table.js +105 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +27 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +1550 -0
- package/dist/prosemirror/conversion/index.d.ts +4 -0
- package/dist/prosemirror/conversion/index.js +4 -0
- package/dist/prosemirror/conversion/runShadingMark.d.ts +16 -0
- package/dist/prosemirror/conversion/runShadingMark.js +39 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +39 -0
- package/dist/prosemirror/conversion/toProseDoc.js +1404 -0
- package/dist/prosemirror/extensions/ExtensionManager.d.ts +43 -0
- package/dist/prosemirror/extensions/ExtensionManager.js +86 -0
- package/dist/prosemirror/extensions/StarterKit.d.ts +16 -0
- package/dist/prosemirror/extensions/StarterKit.js +132 -0
- package/dist/prosemirror/extensions/core/DocExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/core/DocExtension.js +12 -0
- package/dist/prosemirror/extensions/core/HistoryExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/core/HistoryExtension.js +28 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +25 -0
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +619 -0
- package/dist/prosemirror/extensions/core/TextExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/core/TextExtension.js +12 -0
- package/dist/prosemirror/extensions/create.d.ts +17 -0
- package/dist/prosemirror/extensions/create.js +129 -0
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +23 -0
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +106 -0
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.d.ts +8 -0
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +172 -0
- package/dist/prosemirror/extensions/features/BidiShortcutExtension.d.ts +16 -0
- package/dist/prosemirror/extensions/features/BidiShortcutExtension.js +38 -0
- package/dist/prosemirror/extensions/features/ContentControlWidgetsExtension.d.ts +16 -0
- package/dist/prosemirror/extensions/features/ContentControlWidgetsExtension.js +21 -0
- package/dist/prosemirror/extensions/features/DropCursorExtension.d.ts +12 -0
- package/dist/prosemirror/extensions/features/DropCursorExtension.js +20 -0
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.d.ts +8 -0
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +44 -0
- package/dist/prosemirror/extensions/features/GapCursorExtension.d.ts +19 -0
- package/dist/prosemirror/extensions/features/GapCursorExtension.js +24 -0
- package/dist/prosemirror/extensions/features/ImageDragExtension.d.ts +15 -0
- package/dist/prosemirror/extensions/features/ImageDragExtension.js +66 -0
- package/dist/prosemirror/extensions/features/ImagePasteExtension.d.ts +12 -0
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +91 -0
- package/dist/prosemirror/extensions/features/ListExtension.d.ts +14 -0
- package/dist/prosemirror/extensions/features/ListExtension.js +340 -0
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +60 -0
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +35 -0
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +188 -0
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +20 -0
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +34 -0
- package/dist/prosemirror/extensions/features/PasteStyleInlinerExtension.d.ts +20 -0
- package/dist/prosemirror/extensions/features/PasteStyleInlinerExtension.js +145 -0
- package/dist/prosemirror/extensions/features/SelectionTrackerExtension.d.ts +10 -0
- package/dist/prosemirror/extensions/features/SelectionTrackerExtension.js +17 -0
- package/dist/prosemirror/extensions/features/bidiShortcutController.d.ts +31 -0
- package/dist/prosemirror/extensions/features/bidiShortcutController.js +27 -0
- package/dist/prosemirror/extensions/features/pasteCleanup.d.ts +31 -0
- package/dist/prosemirror/extensions/features/pasteCleanup.js +159 -0
- package/dist/prosemirror/extensions/marks/AllCapsExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/AllCapsExtension.js +24 -0
- package/dist/prosemirror/extensions/marks/BoldExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/BoldExtension.js +41 -0
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.d.ts +14 -0
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +64 -0
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +23 -0
- package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +47 -0
- package/dist/prosemirror/extensions/marks/CommentExtension.d.ts +12 -0
- package/dist/prosemirror/extensions/marks/CommentExtension.js +38 -0
- package/dist/prosemirror/extensions/marks/FontFamilyExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/FontFamilyExtension.js +55 -0
- package/dist/prosemirror/extensions/marks/FontSizeExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/FontSizeExtension.js +47 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.d.ts +11 -0
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +92 -0
- package/dist/prosemirror/extensions/marks/HiddenTextExtension.d.ts +23 -0
- package/dist/prosemirror/extensions/marks/HiddenTextExtension.js +35 -0
- package/dist/prosemirror/extensions/marks/HighlightExtension.d.ts +10 -0
- package/dist/prosemirror/extensions/marks/HighlightExtension.js +115 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +146 -0
- package/dist/prosemirror/extensions/marks/ItalicExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/ItalicExtension.js +34 -0
- package/dist/prosemirror/extensions/marks/RtlExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/marks/RtlExtension.js +21 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +11 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +75 -0
- package/dist/prosemirror/extensions/marks/RunShadingExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/marks/RunShadingExtension.js +38 -0
- package/dist/prosemirror/extensions/marks/SmallCapsExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/SmallCapsExtension.js +24 -0
- package/dist/prosemirror/extensions/marks/StrikeExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/StrikeExtension.js +33 -0
- package/dist/prosemirror/extensions/marks/SubscriptExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/SubscriptExtension.js +25 -0
- package/dist/prosemirror/extensions/marks/SuperscriptExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +25 -0
- package/dist/prosemirror/extensions/marks/TextColorExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/TextColorExtension.js +50 -0
- package/dist/prosemirror/extensions/marks/TextEffectExtension.d.ts +6 -0
- package/dist/prosemirror/extensions/marks/TextEffectExtension.js +35 -0
- package/dist/prosemirror/extensions/marks/TextEffectsExtensions.d.ts +31 -0
- package/dist/prosemirror/extensions/marks/TextEffectsExtensions.js +134 -0
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.d.ts +22 -0
- package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +113 -0
- package/dist/prosemirror/extensions/marks/UnderlineExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/marks/UnderlineExtension.js +60 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +34 -0
- package/dist/prosemirror/extensions/marks/markUtils.js +233 -0
- package/dist/prosemirror/extensions/nodes/BlockSdtExtension.d.ts +22 -0
- package/dist/prosemirror/extensions/nodes/BlockSdtExtension.js +122 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +12 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +87 -0
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +38 -0
- package/dist/prosemirror/extensions/nodes/HorizontalRuleExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/nodes/HorizontalRuleExtension.js +18 -0
- package/dist/prosemirror/extensions/nodes/ImageExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +132 -0
- package/dist/prosemirror/extensions/nodes/MathExtension.d.ts +13 -0
- package/dist/prosemirror/extensions/nodes/MathExtension.js +56 -0
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +20 -0
- package/dist/prosemirror/extensions/nodes/SdtExtension.d.ts +12 -0
- package/dist/prosemirror/extensions/nodes/SdtExtension.js +107 -0
- package/dist/prosemirror/extensions/nodes/ShapeExtension.d.ts +30 -0
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +502 -0
- package/dist/prosemirror/extensions/nodes/TabExtension.d.ts +9 -0
- package/dist/prosemirror/extensions/nodes/TabExtension.js +27 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +34 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +1972 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +34 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +150 -0
- package/dist/prosemirror/extensions/types.d.ts +101 -0
- package/dist/prosemirror/extensions/types.js +10 -0
- package/dist/prosemirror/findReplaceSelection.d.ts +23 -0
- package/dist/prosemirror/findReplaceSelection.js +86 -0
- package/dist/prosemirror/index.d.ts +25 -0
- package/dist/prosemirror/index.js +23 -0
- package/dist/prosemirror/insertOperations.d.ts +12 -0
- package/dist/prosemirror/insertOperations.js +19 -0
- package/dist/prosemirror/paragraphDirection.d.ts +42 -0
- package/dist/prosemirror/paragraphDirection.js +33 -0
- package/dist/prosemirror/plugins/aiCitationDecorations.d.ts +40 -0
- package/dist/prosemirror/plugins/aiCitationDecorations.js +90 -0
- package/dist/prosemirror/plugins/aiSuggestionDecorations.d.ts +42 -0
- package/dist/prosemirror/plugins/aiSuggestionDecorations.js +135 -0
- package/dist/prosemirror/plugins/anonymizationDecorations.d.ts +60 -0
- package/dist/prosemirror/plugins/anonymizationDecorations.js +120 -0
- package/dist/prosemirror/plugins/autocompleteSuggestion.d.ts +123 -0
- package/dist/prosemirror/plugins/autocompleteSuggestion.js +283 -0
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +56 -0
- package/dist/prosemirror/plugins/contentControlWidgets.js +192 -0
- package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +37 -0
- package/dist/prosemirror/plugins/createDocScanPlugin.js +55 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +18 -0
- package/dist/prosemirror/plugins/documentStyles.js +46 -0
- package/dist/prosemirror/plugins/index.d.ts +3 -0
- package/dist/prosemirror/plugins/index.js +3 -0
- package/dist/prosemirror/plugins/pmTextScan.d.ts +19 -0
- package/dist/prosemirror/plugins/pmTextScan.js +39 -0
- package/dist/prosemirror/plugins/selectionTracker.d.ts +43 -0
- package/dist/prosemirror/plugins/selectionTracker.js +179 -0
- package/dist/prosemirror/plugins/suggestionMode.d.ts +70 -0
- package/dist/prosemirror/plugins/suggestionMode.js +489 -0
- package/dist/prosemirror/plugins/templateDirectives.d.ts +25 -0
- package/dist/prosemirror/plugins/templateDirectives.js +67 -0
- package/dist/prosemirror/plugins/templatePreviewValues.d.ts +49 -0
- package/dist/prosemirror/plugins/templatePreviewValues.js +117 -0
- package/dist/prosemirror/plugins/templateSlashMenu.d.ts +57 -0
- package/dist/prosemirror/plugins/templateSlashMenu.js +184 -0
- package/dist/prosemirror/schema/index.d.ts +15 -0
- package/dist/prosemirror/schema/index.js +20 -0
- package/dist/prosemirror/schema/marks.d.ts +118 -0
- package/dist/prosemirror/schema/marks.js +0 -0
- package/dist/prosemirror/schema/nodes.d.ts +389 -0
- package/dist/prosemirror/schema/nodes.js +0 -0
- package/dist/prosemirror/selectionState.d.ts +23 -0
- package/dist/prosemirror/selectionState.js +111 -0
- package/dist/prosemirror/styles/index.d.ts +2 -0
- package/dist/prosemirror/styles/index.js +2 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +32 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +108 -0
- package/dist/prosemirror/styles/styleResolver.d.ts +94 -0
- package/dist/prosemirror/styles/styleResolver.js +200 -0
- package/dist/prosemirror/utils/findParagraphByParaId.d.ts +26 -0
- package/dist/prosemirror/utils/findParagraphByParaId.js +37 -0
- package/dist/prosemirror/utils/tabCalculator.d.ts +110 -0
- package/dist/prosemirror/utils/tabCalculator.js +137 -0
- package/dist/prosemirror/validation.d.ts +20 -0
- package/dist/prosemirror/validation.js +177 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.js +6 -0
- package/dist/style-engine/index.d.ts +3 -0
- package/dist/style-engine/index.js +2 -0
- package/dist/style-engine/styleEngine.d.ts +67 -0
- package/dist/style-engine/styleEngine.js +70 -0
- package/dist/types/block-id.d.ts +58 -0
- package/dist/types/block-id.js +61 -0
- package/dist/types/colors.d.ts +2 -0
- package/dist/types/colors.js +0 -0
- package/dist/types/content.d.ts +2 -0
- package/dist/types/content.js +0 -0
- package/dist/types/document.d.ts +7 -0
- package/dist/types/document.js +0 -0
- package/dist/types/documentEnumValues.d.ts +89 -0
- package/dist/types/documentEnumValues.js +693 -0
- package/dist/types/formatting.d.ts +2 -0
- package/dist/types/formatting.js +0 -0
- package/dist/types/index.d.ts +107 -0
- package/dist/types/index.js +0 -0
- package/dist/utils/authorColors.d.ts +16 -0
- package/dist/utils/authorColors.js +30 -0
- package/dist/utils/baseDirection.d.ts +23 -0
- package/dist/utils/baseDirection.js +34 -0
- package/dist/utils/clipboard.d.ts +126 -0
- package/dist/utils/clipboard.js +622 -0
- package/dist/utils/colorResolver.d.ts +158 -0
- package/dist/utils/colorResolver.js +557 -0
- package/dist/utils/createDocument.d.ts +50 -0
- package/dist/utils/createDocument.js +262 -0
- package/dist/utils/documentLoaderBehavior.d.ts +22 -0
- package/dist/utils/documentLoaderBehavior.js +14 -0
- package/dist/utils/docxInput.d.ts +22 -0
- package/dist/utils/docxInput.js +16 -0
- package/dist/utils/domGuards.d.ts +59 -0
- package/dist/utils/domGuards.js +82 -0
- package/dist/utils/fontFamilyMerge.d.ts +7 -0
- package/dist/utils/fontFamilyMerge.js +31 -0
- package/dist/utils/fontLoader.d.ts +50 -0
- package/dist/utils/fontLoader.js +177 -0
- package/dist/utils/fontResolver.d.ts +61 -0
- package/dist/utils/fontResolver.js +651 -0
- package/dist/utils/fontWeights.d.ts +4 -0
- package/dist/utils/fontWeights.js +4 -0
- package/dist/utils/formatToStyle.d.ts +103 -0
- package/dist/utils/formatToStyle.js +289 -0
- package/dist/utils/headerFooter.d.ts +74 -0
- package/dist/utils/headerFooter.js +257 -0
- package/dist/utils/headingCollector.d.ts +22 -0
- package/dist/utils/headingCollector.js +36 -0
- package/dist/utils/hexId.d.ts +33 -0
- package/dist/utils/hexId.js +37 -0
- package/dist/utils/imageValidation.d.ts +5 -0
- package/dist/utils/imageValidation.js +31 -0
- package/dist/utils/paragraphFormattingMerge.d.ts +14 -0
- package/dist/utils/paragraphFormattingMerge.js +68 -0
- package/dist/utils/replaceText.d.ts +17 -0
- package/dist/utils/replaceText.js +161 -0
- package/dist/utils/rotationBoundingBox.d.ts +12 -0
- package/dist/utils/rotationBoundingBox.js +36 -0
- package/dist/utils/scriptSegments.d.ts +36 -0
- package/dist/utils/scriptSegments.js +52 -0
- package/dist/utils/tableOperations.d.ts +87 -0
- package/dist/utils/tableOperations.js +259 -0
- package/dist/utils/textFormattingMerge.d.ts +6 -0
- package/dist/utils/textFormattingMerge.js +31 -0
- package/dist/utils/tiffConverter.d.ts +18 -0
- package/dist/utils/tiffConverter.js +83 -0
- package/dist/utils/units.d.ts +99 -0
- package/dist/utils/units.js +139 -0
- package/dist/utils/urlSecurity.d.ts +7 -0
- package/dist/utils/urlSecurity.js +65 -0
- package/dist/watermark/index.d.ts +39 -0
- package/dist/watermark/index.js +149 -0
- package/package.json +122 -2
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
//#region src/docx/selectiveXmlPatch.ts
|
|
2
|
+
/**
|
|
3
|
+
* Selective XML Patch Module
|
|
4
|
+
*
|
|
5
|
+
* Patches only changed paragraphs in document.xml, preserving
|
|
6
|
+
* unchanged content byte-for-byte. Uses string offset tracking
|
|
7
|
+
* with proper tag depth counting (not regex) to handle nested elements.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Whether `char` ends an element's tag name in XML — a whitespace separator
|
|
11
|
+
* (space, tab, CR, or LF, all valid before attributes per XML 1.0 §3.1), the
|
|
12
|
+
* tag close `>`, or a self-close `/`. Manual tag scanners must accept every
|
|
13
|
+
* whitespace form, not just a literal space, so newline-formatted markup
|
|
14
|
+
* (`<w:p\n w14:paraId="…">`) is still recognized as the element rather than
|
|
15
|
+
* mistaken for a longer-named sibling.
|
|
16
|
+
*/
|
|
17
|
+
function isXmlNameBoundary(char) {
|
|
18
|
+
return char === " " || char === " " || char === "\n" || char === "\r" || char === ">" || char === "/";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Find the exact string start and end offsets of a <w:p> element
|
|
22
|
+
* identified by its w14:paraId attribute.
|
|
23
|
+
*
|
|
24
|
+
* Handles nested <w:p> elements (e.g. inside mc:AlternateContent)
|
|
25
|
+
* via proper depth counting.
|
|
26
|
+
*
|
|
27
|
+
* Returns null if paraId not found or appears more than once (ambiguous).
|
|
28
|
+
*/
|
|
29
|
+
function findParagraphOffsets(xml, paraId) {
|
|
30
|
+
const escaped = escapeRegExp(paraId);
|
|
31
|
+
const pattern = new RegExp(`<w:p[\\s][^>]*w14:paraId="${escaped}"`, "gu");
|
|
32
|
+
const matches = [];
|
|
33
|
+
let match;
|
|
34
|
+
while ((match = pattern.exec(xml)) !== null) matches.push(match.index);
|
|
35
|
+
if (matches.length === 0) return null;
|
|
36
|
+
if (matches.length > 1) return null;
|
|
37
|
+
const start = matches[0];
|
|
38
|
+
let pos = start;
|
|
39
|
+
let depth = 0;
|
|
40
|
+
while (pos < xml.length) {
|
|
41
|
+
const tagStart = xml.indexOf("<", pos);
|
|
42
|
+
if (tagStart === -1) break;
|
|
43
|
+
if (xml.startsWith("<w:p", tagStart)) {
|
|
44
|
+
const charAfterTag = xml[tagStart + 4];
|
|
45
|
+
if (isXmlNameBoundary(charAfterTag)) {
|
|
46
|
+
const tagEnd = xml.indexOf(">", tagStart);
|
|
47
|
+
if (tagEnd === -1) break;
|
|
48
|
+
if (xml[tagEnd - 1] === "/") {
|
|
49
|
+
if (depth === 0) return {
|
|
50
|
+
start,
|
|
51
|
+
end: tagEnd + 1
|
|
52
|
+
};
|
|
53
|
+
pos = tagEnd + 1;
|
|
54
|
+
} else {
|
|
55
|
+
depth++;
|
|
56
|
+
pos = tagEnd + 1;
|
|
57
|
+
}
|
|
58
|
+
} else pos = tagStart + 1;
|
|
59
|
+
} else if (xml.startsWith("</w:p>", tagStart)) {
|
|
60
|
+
depth--;
|
|
61
|
+
if (depth === 0) return {
|
|
62
|
+
start,
|
|
63
|
+
end: tagStart + 6
|
|
64
|
+
};
|
|
65
|
+
pos = tagStart + 6;
|
|
66
|
+
} else pos = tagStart + 1;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Extract the serialized XML for a specific paragraph by paraId
|
|
72
|
+
* from a fully serialized document.xml string.
|
|
73
|
+
*/
|
|
74
|
+
function extractParagraphXml(serializedXml, paraId) {
|
|
75
|
+
const offsets = findParagraphOffsets(serializedXml, paraId);
|
|
76
|
+
if (!offsets) return null;
|
|
77
|
+
return serializedXml.slice(offsets.start, offsets.end);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Count <w:p> elements in an XML string (top-level paragraph count).
|
|
81
|
+
* Counts opening <w:p tags that are NOT self-closing.
|
|
82
|
+
*/
|
|
83
|
+
function countParagraphElements(xml) {
|
|
84
|
+
let count = 0;
|
|
85
|
+
const pattern = /<w:p[\s>]/gu;
|
|
86
|
+
let match;
|
|
87
|
+
while ((match = pattern.exec(xml)) !== null) {
|
|
88
|
+
const idx = match.index;
|
|
89
|
+
if (isXmlNameBoundary(xml[idx + 4])) count++;
|
|
90
|
+
}
|
|
91
|
+
return count;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Find all paraIds in an XML string and return counts (to detect duplicates).
|
|
95
|
+
*/
|
|
96
|
+
function collectParaIds(xml) {
|
|
97
|
+
const ids = /* @__PURE__ */ new Map();
|
|
98
|
+
const pattern = /w14:paraId="(?<id>[^"]+)"/gu;
|
|
99
|
+
let match;
|
|
100
|
+
while ((match = pattern.exec(xml)) !== null) {
|
|
101
|
+
const id = match.groups["id"];
|
|
102
|
+
ids.set(id, (ids.get(id) ?? 0) + 1);
|
|
103
|
+
}
|
|
104
|
+
return ids;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Validate that a selective patch can be safely applied.
|
|
108
|
+
*
|
|
109
|
+
* Checks:
|
|
110
|
+
* - All changed paraIds exist in original XML (exactly once)
|
|
111
|
+
* - All changed paraIds exist in serialized XML (exactly once)
|
|
112
|
+
* - Paragraph count matches between original and serialized (unless disabled)
|
|
113
|
+
*/
|
|
114
|
+
function validatePatchSafety(originalXml, serializedXml, changedIds, options = {}) {
|
|
115
|
+
if (changedIds.size === 0) return { safe: true };
|
|
116
|
+
const originalParaIds = collectParaIds(originalXml);
|
|
117
|
+
const serializedParaIds = collectParaIds(serializedXml);
|
|
118
|
+
for (const id of changedIds) {
|
|
119
|
+
const origCount = originalParaIds.get(id) || 0;
|
|
120
|
+
if (origCount === 0) return {
|
|
121
|
+
safe: false,
|
|
122
|
+
reason: `paraId-not-found-in-original: ${id}`
|
|
123
|
+
};
|
|
124
|
+
if (origCount > 1) return {
|
|
125
|
+
safe: false,
|
|
126
|
+
reason: `duplicate-paraId-in-original: ${id}`
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
for (const id of changedIds) {
|
|
130
|
+
const serCount = serializedParaIds.get(id) || 0;
|
|
131
|
+
if (serCount === 0) return {
|
|
132
|
+
safe: false,
|
|
133
|
+
reason: `paraId-not-found-in-serialized: ${id}`
|
|
134
|
+
};
|
|
135
|
+
if (serCount > 1) return {
|
|
136
|
+
safe: false,
|
|
137
|
+
reason: `duplicate-paraId-in-serialized: ${id}`
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (options.checkParagraphCount === false) return { safe: true };
|
|
141
|
+
const originalCount = countParagraphElements(originalXml);
|
|
142
|
+
const serializedCount = countParagraphElements(serializedXml);
|
|
143
|
+
if (originalCount !== serializedCount) return {
|
|
144
|
+
safe: false,
|
|
145
|
+
reason: `paragraph-count-mismatch: original=${originalCount}, serialized=${serializedCount}`
|
|
146
|
+
};
|
|
147
|
+
return { safe: true };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Build a patched document.xml by splicing new paragraph XML into
|
|
151
|
+
* the original at the correct offsets. Only changed paragraphs
|
|
152
|
+
* are replaced; everything else is preserved byte-for-byte.
|
|
153
|
+
*
|
|
154
|
+
* Returns null if any step fails.
|
|
155
|
+
*/
|
|
156
|
+
function buildPatchedDocumentXml(originalXml, serializedXml, changedIds) {
|
|
157
|
+
if (changedIds.size === 0) return originalXml;
|
|
158
|
+
if (!validatePatchSafety(originalXml, serializedXml, changedIds).safe) return null;
|
|
159
|
+
return spliceChangedParagraphs(originalXml, serializedXml, changedIds);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Build a patched note part (word/footnotes.xml / word/endnotes.xml) by
|
|
163
|
+
* splicing edited note paragraphs into the original, preserving unchanged
|
|
164
|
+
* content byte-for-byte.
|
|
165
|
+
*
|
|
166
|
+
* Unlike {@link buildPatchedDocumentXml} this does NOT require the paragraph
|
|
167
|
+
* counts to match: the document model only retains the normal notes, so the
|
|
168
|
+
* serialized note XML omits the separator / continuationSeparator paragraphs
|
|
169
|
+
* the original part still carries. Splicing by `paraId` keeps those separators
|
|
170
|
+
* and every unedited note byte-exact while replacing only the edited ones.
|
|
171
|
+
*
|
|
172
|
+
* Returns null if any changed id is missing or ambiguous in either input, so
|
|
173
|
+
* the caller can fall back to preserving the original part verbatim.
|
|
174
|
+
*/
|
|
175
|
+
function buildPatchedNoteXml(originalXml, serializedXml, changedIds) {
|
|
176
|
+
if (changedIds.size === 0) return originalXml;
|
|
177
|
+
if (!validatePatchSafety(originalXml, serializedXml, changedIds, { checkParagraphCount: false }).safe) return null;
|
|
178
|
+
return spliceChangedParagraphs(originalXml, serializedXml, changedIds);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Replace each changed paragraph in `originalXml` with its re-serialized form
|
|
182
|
+
* extracted from `serializedXml`, splicing end-to-start so earlier offsets stay
|
|
183
|
+
* valid. Assumes safety has already been validated. Returns null if an offset
|
|
184
|
+
* or extraction unexpectedly fails.
|
|
185
|
+
*/
|
|
186
|
+
function spliceChangedParagraphs(originalXml, serializedXml, changedIds) {
|
|
187
|
+
const replacements = [];
|
|
188
|
+
for (const paraId of changedIds) {
|
|
189
|
+
const origOffsets = findParagraphOffsets(originalXml, paraId);
|
|
190
|
+
if (!origOffsets) return null;
|
|
191
|
+
const newXml = extractParagraphXml(serializedXml, paraId);
|
|
192
|
+
if (!newXml) return null;
|
|
193
|
+
replacements.push({
|
|
194
|
+
start: origOffsets.start,
|
|
195
|
+
end: origOffsets.end,
|
|
196
|
+
newXml
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
replacements.sort((a, b) => b.start - a.start);
|
|
200
|
+
let result = originalXml;
|
|
201
|
+
for (const { start, end, newXml } of replacements) result = result.slice(0, start) + newXml + result.slice(end);
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Depth-count the end of the element that opens at `start` (an `<openLiteral…>`
|
|
206
|
+
* offset), returning its full range. Nested same-name opens increment depth;
|
|
207
|
+
* the matching `closeTag` (or a self-close) at depth 0 ends it. The boundary
|
|
208
|
+
* check skips longer-named siblings (`<w:numFmt>` when scanning `<w:num`).
|
|
209
|
+
*/
|
|
210
|
+
function scanElementRange(xml, start, openLiteral, closeTag) {
|
|
211
|
+
const afterOpenIndex = openLiteral.length;
|
|
212
|
+
let pos = start;
|
|
213
|
+
let depth = 0;
|
|
214
|
+
while (pos < xml.length) {
|
|
215
|
+
const tagStart = xml.indexOf("<", pos);
|
|
216
|
+
if (tagStart === -1) break;
|
|
217
|
+
if (xml.startsWith(openLiteral, tagStart)) {
|
|
218
|
+
if (!isXmlNameBoundary(xml[tagStart + afterOpenIndex])) {
|
|
219
|
+
pos = tagStart + 1;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
const tagEnd = xml.indexOf(">", tagStart);
|
|
223
|
+
if (tagEnd === -1) break;
|
|
224
|
+
if (xml[tagEnd - 1] === "/") {
|
|
225
|
+
if (depth === 0) return {
|
|
226
|
+
start,
|
|
227
|
+
end: tagEnd + 1
|
|
228
|
+
};
|
|
229
|
+
pos = tagEnd + 1;
|
|
230
|
+
} else {
|
|
231
|
+
depth++;
|
|
232
|
+
pos = tagEnd + 1;
|
|
233
|
+
}
|
|
234
|
+
} else if (xml.startsWith(closeTag, tagStart)) {
|
|
235
|
+
depth--;
|
|
236
|
+
if (depth === 0) return {
|
|
237
|
+
start,
|
|
238
|
+
end: tagStart + closeTag.length
|
|
239
|
+
};
|
|
240
|
+
pos = tagStart + closeTag.length;
|
|
241
|
+
} else pos = tagStart + 1;
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Find the exact start/end offsets of the element `<openLiteral … idAttr="id">`,
|
|
247
|
+
* depth-counting its matching close tag. Returns null when the id is absent or
|
|
248
|
+
* ambiguous (appears more than once).
|
|
249
|
+
*/
|
|
250
|
+
function findElementByIdAttr(xml, openLiteral, closeTag, idAttr, id) {
|
|
251
|
+
const pattern = new RegExp(`${escapeRegExp(openLiteral)}[\\s][^>]*${escapeRegExp(idAttr)}="${escapeRegExp(id)}"`, "gu");
|
|
252
|
+
const matches = [];
|
|
253
|
+
let match;
|
|
254
|
+
while ((match = pattern.exec(xml)) !== null) matches.push(match.index);
|
|
255
|
+
if (matches.length !== 1) return null;
|
|
256
|
+
return scanElementRange(xml, matches[0], openLiteral, closeTag);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Extract the serialized XML for `<openLiteral … idAttr="id">…`, or null when it
|
|
260
|
+
* cannot be resolved uniquely.
|
|
261
|
+
*/
|
|
262
|
+
function extractElementByIdAttr(xml, openLiteral, closeTag, idAttr, id) {
|
|
263
|
+
const offsets = findElementByIdAttr(xml, openLiteral, closeTag, idAttr, id);
|
|
264
|
+
return offsets ? xml.slice(offsets.start, offsets.end) : null;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The full range of the first `<openLiteral …>…</closeTag>` element, or null.
|
|
268
|
+
* Used to locate an unkeyed sub-element (a level's `mc:AlternateContent`).
|
|
269
|
+
*/
|
|
270
|
+
function findFirstElement(xml, openLiteral, closeTag) {
|
|
271
|
+
let pos = 0;
|
|
272
|
+
while (pos < xml.length) {
|
|
273
|
+
const idx = xml.indexOf(openLiteral, pos);
|
|
274
|
+
if (idx === -1) return null;
|
|
275
|
+
if (isXmlNameBoundary(xml[idx + openLiteral.length])) return scanElementRange(xml, idx, openLiteral, closeTag);
|
|
276
|
+
pos = idx + 1;
|
|
277
|
+
}
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Collect the ids carried by opening `<openLiteral … idAttr="…">` tags, with
|
|
282
|
+
* counts so duplicates can be rejected. The `[\s]` after the literal restricts
|
|
283
|
+
* matches to the exact element (excluding `<w:numFmt` when scanning `<w:num`).
|
|
284
|
+
*/
|
|
285
|
+
function collectElementIds(xml, openLiteral, idAttr) {
|
|
286
|
+
const ids = /* @__PURE__ */ new Map();
|
|
287
|
+
const pattern = new RegExp(`${escapeRegExp(openLiteral)}[\\s][^>]*?${escapeRegExp(idAttr)}="(?<id>[^"]+)"`, "gu");
|
|
288
|
+
let match;
|
|
289
|
+
while ((match = pattern.exec(xml)) !== null) {
|
|
290
|
+
const id = match.groups["id"];
|
|
291
|
+
ids.set(id, (ids.get(id) ?? 0) + 1);
|
|
292
|
+
}
|
|
293
|
+
return ids;
|
|
294
|
+
}
|
|
295
|
+
const NUMBERING_OPEN_LITERAL = {
|
|
296
|
+
abstractNum: "<w:abstractNum",
|
|
297
|
+
num: "<w:num"
|
|
298
|
+
};
|
|
299
|
+
const NUMBERING_CLOSE_TAG = {
|
|
300
|
+
abstractNum: "</w:abstractNum>",
|
|
301
|
+
num: "</w:num>"
|
|
302
|
+
};
|
|
303
|
+
const NUMBERING_ID_ATTR = {
|
|
304
|
+
abstractNum: "w:abstractNumId",
|
|
305
|
+
num: "w:numId"
|
|
306
|
+
};
|
|
307
|
+
const LEVEL_OPEN_LITERAL = "<w:lvl";
|
|
308
|
+
const LEVEL_CLOSE_TAG = "</w:lvl>";
|
|
309
|
+
const LEVEL_ID_ATTR = "w:ilvl";
|
|
310
|
+
function findNumberingElementOffsets(xml, kind, id) {
|
|
311
|
+
return findElementByIdAttr(xml, NUMBERING_OPEN_LITERAL[kind], NUMBERING_CLOSE_TAG[kind], NUMBERING_ID_ATTR[kind], id);
|
|
312
|
+
}
|
|
313
|
+
function extractNumberingElementXml(xml, kind, id) {
|
|
314
|
+
return extractElementByIdAttr(xml, NUMBERING_OPEN_LITERAL[kind], NUMBERING_CLOSE_TAG[kind], NUMBERING_ID_ATTR[kind], id);
|
|
315
|
+
}
|
|
316
|
+
function collectNumberingElementIds(xml, kind) {
|
|
317
|
+
return collectElementIds(xml, NUMBERING_OPEN_LITERAL[kind], NUMBERING_ID_ATTR[kind]);
|
|
318
|
+
}
|
|
319
|
+
const SYNTHETIC_NUM_FMT_PATTERN = /<w:numFmt w:val="decimalZero(?<width>[345])"\/>/u;
|
|
320
|
+
/**
|
|
321
|
+
* The numbering definitions whose current serialization differs from the
|
|
322
|
+
* baseline (re-parsed original) serialization — the ones actually edited. An id
|
|
323
|
+
* is only considered when it resolves uniquely in BOTH inputs, so a definition
|
|
324
|
+
* added or removed relative to the original (which cannot be spliced by id) is
|
|
325
|
+
* left out; both save paths defer those to the byte-exact original part.
|
|
326
|
+
*/
|
|
327
|
+
function collectChangedNumberingDefs(baselineXml, currentXml) {
|
|
328
|
+
const changedForKind = (kind) => {
|
|
329
|
+
const changed = /* @__PURE__ */ new Set();
|
|
330
|
+
const baselineIds = collectNumberingElementIds(baselineXml, kind);
|
|
331
|
+
for (const [id, count] of collectNumberingElementIds(currentXml, kind)) {
|
|
332
|
+
if (count !== 1 || baselineIds.get(id) !== 1) continue;
|
|
333
|
+
const before = extractNumberingElementXml(baselineXml, kind, id);
|
|
334
|
+
const after = extractNumberingElementXml(currentXml, kind, id);
|
|
335
|
+
if (before !== null && after !== null && before !== after) changed.add(id);
|
|
336
|
+
}
|
|
337
|
+
return changed;
|
|
338
|
+
};
|
|
339
|
+
return {
|
|
340
|
+
abstractNums: changedForKind("abstractNum"),
|
|
341
|
+
nums: changedForKind("num")
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* The element representing a level's number format in the source XML: the
|
|
346
|
+
* `<mc:AlternateContent>` block Word wraps a custom format in, else a
|
|
347
|
+
* self-closing `<w:numFmt …/>` (covers `<w:numFmt w:val="custom" w:format=…/>`).
|
|
348
|
+
*/
|
|
349
|
+
function extractLevelNumFmtElement(levelXml) {
|
|
350
|
+
const alt = findFirstElement(levelXml, "<mc:AlternateContent", "</mc:AlternateContent>");
|
|
351
|
+
if (alt) return levelXml.slice(alt.start, alt.end);
|
|
352
|
+
const match = /<w:numFmt\b[^>]*\/>/u.exec(levelXml);
|
|
353
|
+
return match ? match[0] : null;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* A valid OOXML custom number format equivalent to a `decimalZero{width}`
|
|
357
|
+
* synthetic value: a zero-padded first token folio's parser reads back to the
|
|
358
|
+
* same width. Used only when the original element cannot be resolved, so a
|
|
359
|
+
* changed definition never emits a non-OOXML synthetic value.
|
|
360
|
+
*/
|
|
361
|
+
function reconstructCustomNumFmt(width) {
|
|
362
|
+
return `<w:numFmt w:val="custom" w:format="${`${"0".repeat(Number.parseInt(width, 10) - 1)}1`}"/>`;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* The synthetic `decimalZero{width}` width the parser would derive from an
|
|
366
|
+
* original level's number-format element (its custom `w:format` first token),
|
|
367
|
+
* as the same digit-count string the SYNTHETIC_NUM_FMT_PATTERN captures. Mirrors
|
|
368
|
+
* `parseCustomNumberFormat` (first comma-separated token, `^0+1$`, clamped to 5).
|
|
369
|
+
* Returns null when the element carries no zero-padded custom format, so a
|
|
370
|
+
* genuine format change is never mistaken for the original.
|
|
371
|
+
*/
|
|
372
|
+
function originalNumFmtWidth(numFmtElement) {
|
|
373
|
+
for (const match of numFmtElement.matchAll(/<w:numFmt\b[^>]*\/>/gu)) {
|
|
374
|
+
const tag = match[0];
|
|
375
|
+
if (!/\bw:val="custom"/u.test(tag)) continue;
|
|
376
|
+
const format = /\bw:format="(?<format>[^"]*)"/u.exec(tag)?.groups?.["format"];
|
|
377
|
+
if (format === void 0) continue;
|
|
378
|
+
const firstToken = format.split(",")[0]?.trim() ?? "";
|
|
379
|
+
return /^0+1$/u.test(firstToken) ? String(Math.min(firstToken.length, 5)) : null;
|
|
380
|
+
}
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Collect the `xmlns` / `xmlns:*` declarations from an element's opening tag
|
|
385
|
+
* (the substring up to its first `>`).
|
|
386
|
+
*/
|
|
387
|
+
function collectXmlnsFromOpeningTag(elementXml) {
|
|
388
|
+
const out = {};
|
|
389
|
+
const tagEnd = elementXml.indexOf(">");
|
|
390
|
+
const openTag = tagEnd === -1 ? elementXml : elementXml.slice(0, tagEnd);
|
|
391
|
+
const pattern = /\s(?<name>xmlns(?::[\w.-]+)?)="(?<uri>[^"]*)"/gu;
|
|
392
|
+
let match;
|
|
393
|
+
while ((match = pattern.exec(openTag)) !== null) out[match.groups["name"]] = match.groups["uri"];
|
|
394
|
+
return out;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Carry the given `xmlns` declarations onto `fragmentXml`'s root element so it
|
|
398
|
+
* resolves every prefix even after the ancestor that declared them is replaced.
|
|
399
|
+
* Declarations the fragment already carries win (mirrors the VML
|
|
400
|
+
* `cloneWithXmlnsDeclarations` self-contained-clone behaviour, in the string
|
|
401
|
+
* domain the byte-exact splice needs).
|
|
402
|
+
*/
|
|
403
|
+
function withXmlnsDeclarations(fragmentXml, xmlnsDecls) {
|
|
404
|
+
const own = collectXmlnsFromOpeningTag(fragmentXml);
|
|
405
|
+
const additions = Object.entries(xmlnsDecls).filter(([name]) => !(name in own)).map(([name, uri]) => ` ${name}="${uri}"`);
|
|
406
|
+
if (additions.length === 0) return fragmentXml;
|
|
407
|
+
let nameEnd = 1;
|
|
408
|
+
while (nameEnd < fragmentXml.length && !isXmlNameBoundary(fragmentXml[nameEnd])) nameEnd += 1;
|
|
409
|
+
return fragmentXml.slice(0, nameEnd) + additions.join("") + fragmentXml.slice(nameEnd);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Swap each synthetic `decimalZero{3,4,5}` numFmt in a re-serialized definition
|
|
413
|
+
* back to the original level's number-format element.
|
|
414
|
+
*
|
|
415
|
+
* folio's parser collapses a Word custom / mc:AlternateContent number format
|
|
416
|
+
* into a synthetic `decimalZero{3,4,5}` value the model cannot re-emit as valid
|
|
417
|
+
* OOXML. When an unrelated field of the definition is edited, the whole
|
|
418
|
+
* definition is re-serialized, so without this pass the level's custom format
|
|
419
|
+
* would be replaced by an invalid value and lost on reparse. For each level
|
|
420
|
+
* whose re-emitted numFmt is synthetic, restore the original level's numFmt
|
|
421
|
+
* element by ilvl ONLY when the model's synthetic value still matches the
|
|
422
|
+
* original's (the format was not edited, just preserved past an unrelated
|
|
423
|
+
* change). When the model deliberately changed the width (e.g. decimalZero4 ->
|
|
424
|
+
* decimalZero5), or the original cannot be resolved, emit a valid OOXML custom
|
|
425
|
+
* format for the CURRENT width instead — honoring the edit and never leaving a
|
|
426
|
+
* synthetic value.
|
|
427
|
+
*/
|
|
428
|
+
function restoreLevelNumFmts(originalDefXml, currentDefXml) {
|
|
429
|
+
const replacements = [];
|
|
430
|
+
for (const [ilvl, count] of collectElementIds(currentDefXml, LEVEL_OPEN_LITERAL, LEVEL_ID_ATTR)) {
|
|
431
|
+
if (count !== 1) continue;
|
|
432
|
+
const curOffsets = findElementByIdAttr(currentDefXml, LEVEL_OPEN_LITERAL, LEVEL_CLOSE_TAG, LEVEL_ID_ATTR, ilvl);
|
|
433
|
+
if (!curOffsets) continue;
|
|
434
|
+
const curLevel = currentDefXml.slice(curOffsets.start, curOffsets.end);
|
|
435
|
+
const synthetic = SYNTHETIC_NUM_FMT_PATTERN.exec(curLevel);
|
|
436
|
+
if (!synthetic) continue;
|
|
437
|
+
const origLevel = extractElementByIdAttr(originalDefXml, LEVEL_OPEN_LITERAL, LEVEL_CLOSE_TAG, LEVEL_ID_ATTR, ilvl);
|
|
438
|
+
const currentWidth = synthetic.groups["width"];
|
|
439
|
+
const original = origLevel ? extractLevelNumFmtElement(origLevel) : null;
|
|
440
|
+
let replacement;
|
|
441
|
+
if (original && origLevel && originalNumFmtWidth(original) === currentWidth) replacement = withXmlnsDeclarations(original, {
|
|
442
|
+
...collectXmlnsFromOpeningTag(originalDefXml),
|
|
443
|
+
...collectXmlnsFromOpeningTag(origLevel)
|
|
444
|
+
});
|
|
445
|
+
else replacement = reconstructCustomNumFmt(currentWidth);
|
|
446
|
+
const restoredLevel = curLevel.slice(0, synthetic.index) + replacement + curLevel.slice(synthetic.index + synthetic[0].length);
|
|
447
|
+
replacements.push({
|
|
448
|
+
start: curOffsets.start,
|
|
449
|
+
end: curOffsets.end,
|
|
450
|
+
newXml: restoredLevel
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
replacements.sort((a, b) => b.start - a.start);
|
|
454
|
+
let result = currentDefXml;
|
|
455
|
+
for (const { start, end, newXml } of replacements) result = result.slice(0, start) + newXml + result.slice(end);
|
|
456
|
+
return result;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Build a patched `word/numbering.xml` by splicing the changed `w:abstractNum` /
|
|
460
|
+
* `w:num` definitions from `currentXml` (the model's serialization) into
|
|
461
|
+
* `originalXml`, preserving every other byte. Returns the original unchanged
|
|
462
|
+
* when nothing changed, or null when a changed id cannot be resolved uniquely
|
|
463
|
+
* in either input (so the caller preserves the original part verbatim).
|
|
464
|
+
*/
|
|
465
|
+
function buildPatchedNumberingXml(originalXml, currentXml, changed) {
|
|
466
|
+
if (changed.abstractNums.size === 0 && changed.nums.size === 0) return originalXml;
|
|
467
|
+
const replacements = [];
|
|
468
|
+
const collect = (kind, ids) => {
|
|
469
|
+
for (const id of ids) {
|
|
470
|
+
const origOffsets = findNumberingElementOffsets(originalXml, kind, id);
|
|
471
|
+
if (!origOffsets) return false;
|
|
472
|
+
const reserialized = extractNumberingElementXml(currentXml, kind, id);
|
|
473
|
+
if (reserialized === null) return false;
|
|
474
|
+
const newXml = restoreLevelNumFmts(originalXml.slice(origOffsets.start, origOffsets.end), reserialized);
|
|
475
|
+
replacements.push({
|
|
476
|
+
start: origOffsets.start,
|
|
477
|
+
end: origOffsets.end,
|
|
478
|
+
newXml
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
return true;
|
|
482
|
+
};
|
|
483
|
+
if (!collect("abstractNum", changed.abstractNums) || !collect("num", changed.nums)) return null;
|
|
484
|
+
replacements.sort((a, b) => b.start - a.start);
|
|
485
|
+
let result = originalXml;
|
|
486
|
+
for (const { start, end, newXml } of replacements) result = result.slice(0, start) + newXml + result.slice(end);
|
|
487
|
+
return result;
|
|
488
|
+
}
|
|
489
|
+
function escapeRegExp(str) {
|
|
490
|
+
return str.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
491
|
+
}
|
|
492
|
+
//#endregion
|
|
493
|
+
export { buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, validatePatchSafety };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
|
|
3
|
+
//#region src/docx/serializer/blockSdtSerializer.d.ts
|
|
4
|
+
declare function serializeBlockSdt(blockSdt: document_d_exports.BlockSdt, serializeChild: (block: document_d_exports.BlockContent) => string): string;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { serializeBlockSdt };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { reconcileRawSdtPr } from "../sdtPropertiesPatch.js";
|
|
2
|
+
//#region src/docx/serializer/blockSdtSerializer.ts
|
|
3
|
+
function escapeXmlAttr(value) {
|
|
4
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """);
|
|
5
|
+
}
|
|
6
|
+
function serializeFallbackSdtPr(props) {
|
|
7
|
+
const parts = [];
|
|
8
|
+
if (props.id !== void 0) parts.push(`<w:id w:val="${props.id}"/>`);
|
|
9
|
+
if (props.alias) parts.push(`<w:alias w:val="${escapeXmlAttr(props.alias)}"/>`);
|
|
10
|
+
if (props.tag) parts.push(`<w:tag w:val="${escapeXmlAttr(props.tag)}"/>`);
|
|
11
|
+
if (props.lock) parts.push(`<w:lock w:val="${props.lock}"/>`);
|
|
12
|
+
if (props.placeholder) parts.push(`<w:placeholder><w:docPart w:val="${escapeXmlAttr(props.placeholder)}"/></w:placeholder>`);
|
|
13
|
+
if (props.showingPlaceholder) parts.push("<w:showingPlcHdr/>");
|
|
14
|
+
switch (props.sdtType) {
|
|
15
|
+
case "plainText":
|
|
16
|
+
parts.push("<w:text/>");
|
|
17
|
+
break;
|
|
18
|
+
case "date": {
|
|
19
|
+
const fullDateAttr = props.dateValueISO ? ` w:fullDate="${escapeXmlAttr(props.dateValueISO)}"` : "";
|
|
20
|
+
const formatChild = props.dateFormat ? `<w:dateFormat w:val="${escapeXmlAttr(props.dateFormat)}"/>` : "";
|
|
21
|
+
if (fullDateAttr || formatChild) parts.push(`<w:date${fullDateAttr}>${formatChild}</w:date>`);
|
|
22
|
+
else parts.push("<w:date/>");
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case "dropdown":
|
|
26
|
+
case "comboBox": {
|
|
27
|
+
const tag = props.sdtType === "dropdown" ? "w:dropDownList" : "w:comboBox";
|
|
28
|
+
const items = (props.listItems ?? []).map((item) => `<w:listItem w:displayText="${escapeXmlAttr(item.displayText)}" w:value="${escapeXmlAttr(item.value)}"/>`).join("");
|
|
29
|
+
parts.push(`<${tag}>${items}</${tag}>`);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case "checkbox": {
|
|
33
|
+
const val = props.checked ? "1" : "0";
|
|
34
|
+
parts.push(`<w14:checkbox><w14:checked w14:val="${val}"/></w14:checkbox>`);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case "picture":
|
|
38
|
+
parts.push("<w:picture/>");
|
|
39
|
+
break;
|
|
40
|
+
case "buildingBlockGallery":
|
|
41
|
+
parts.push("<w:docPartObj/>");
|
|
42
|
+
break;
|
|
43
|
+
case "group":
|
|
44
|
+
parts.push("<w:group/>");
|
|
45
|
+
break;
|
|
46
|
+
default: break;
|
|
47
|
+
}
|
|
48
|
+
return `<w:sdtPr>${parts.join("")}</w:sdtPr>`;
|
|
49
|
+
}
|
|
50
|
+
function extractDropdownLastValue(blockSdt) {
|
|
51
|
+
if (blockSdt.properties.sdtType !== "dropdown" && blockSdt.properties.sdtType !== "comboBox") return;
|
|
52
|
+
const modeled = blockSdt.properties.dropdownLastValue;
|
|
53
|
+
if (modeled !== void 0) return modeled;
|
|
54
|
+
const firstBlock = blockSdt.content[0];
|
|
55
|
+
if (!firstBlock || firstBlock.type !== "paragraph") return;
|
|
56
|
+
const parts = [];
|
|
57
|
+
for (const child of firstBlock.content) if (child.type === "run") {
|
|
58
|
+
for (const item of child.content) if (item.type === "text") parts.push(item.text);
|
|
59
|
+
}
|
|
60
|
+
const text = parts.join("");
|
|
61
|
+
if (text.length === 0) return;
|
|
62
|
+
const items = blockSdt.properties.listItems;
|
|
63
|
+
if (items) {
|
|
64
|
+
const match = items.find((item) => item.displayText === text);
|
|
65
|
+
if (match) return match.value;
|
|
66
|
+
}
|
|
67
|
+
return text;
|
|
68
|
+
}
|
|
69
|
+
function extractDateFullDate(blockSdt) {
|
|
70
|
+
if (blockSdt.properties.sdtType !== "date") return;
|
|
71
|
+
const iso = blockSdt.properties.dateValueISO;
|
|
72
|
+
return iso !== void 0 && iso.length > 0 ? iso : void 0;
|
|
73
|
+
}
|
|
74
|
+
function serializeBlockSdt(blockSdt, serializeChild) {
|
|
75
|
+
const props = blockSdt.properties;
|
|
76
|
+
const baseSdtPr = props.rawPropertiesXml ?? serializeFallbackSdtPr(props);
|
|
77
|
+
const dateFullDate = extractDateFullDate(blockSdt);
|
|
78
|
+
const dropdownLastValue = extractDropdownLastValue(blockSdt);
|
|
79
|
+
const sdtPrXml = reconcileRawSdtPr(baseSdtPr, props, {
|
|
80
|
+
...dateFullDate !== void 0 ? { dateFullDate } : {},
|
|
81
|
+
...dropdownLastValue !== void 0 ? { dropdownLastValue } : {}
|
|
82
|
+
});
|
|
83
|
+
const sdtEndPrXml = props.rawEndPropertiesXml ?? "";
|
|
84
|
+
const contentXml = blockSdt.content.map(serializeChild).join("");
|
|
85
|
+
return `<w:sdt>${sdtPrXml}${sdtEndPrXml}${props.rawSdtChildrenBeforeContent ?? ""}<w:sdtContent>${contentXml}</w:sdtContent>${props.rawSdtChildrenAfterContent ?? ""}</w:sdt>`;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { serializeBlockSdt };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { document_d_exports } from "../../types/document.js";
|
|
2
|
+
|
|
3
|
+
//#region src/docx/serializer/borderSerializer.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Serialize a single border element (`<w:top .../>`, `<w:left .../>`, ...).
|
|
6
|
+
*
|
|
7
|
+
* `nil`/`none` mean "no border", but an *explicit* one overrides an inherited
|
|
8
|
+
* border (a table-level grid via `w:tblBorders`, a paragraph-style border, a
|
|
9
|
+
* section page border), so it must still round-trip as `<w:side w:val="nil"/>`.
|
|
10
|
+
* A `BorderSpec` only reaches here when the source set it or the user turned the
|
|
11
|
+
* border off, so emitting it is faithful, not noise — dropping it silently
|
|
12
|
+
* re-inherited the container default (e.g. hidden table gridlines reappeared as
|
|
13
|
+
* a full grid on reload). A `nil`/`none` side usually carries no
|
|
14
|
+
* size/color/space, but Word writes `w:sz="0" w:space="0" w:color="auto"` on a
|
|
15
|
+
* turned-off side; those are emitted when present so the value survives a
|
|
16
|
+
* save→parse round-trip and is not otherwise added.
|
|
17
|
+
*
|
|
18
|
+
* `style` and the color values come straight from the parsed DOCX (the parser
|
|
19
|
+
* casts `w:val`/`w:color` without validating the enum), so they are
|
|
20
|
+
* untrusted and are `escapeXml`'d before re-entering XML attributes; for valid
|
|
21
|
+
* documents these are enum/hex values, so escaping is a no-op.
|
|
22
|
+
*/
|
|
23
|
+
declare function serializeBorder(border: document_d_exports.BorderSpec | undefined, elementName: string): string;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { serializeBorder };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { escapeXml, intAttr } from "./xmlUtils.js";
|
|
2
|
+
//#region src/docx/serializer/borderSerializer.ts
|
|
3
|
+
/**
|
|
4
|
+
* Serialize a single border element (`<w:top .../>`, `<w:left .../>`, ...).
|
|
5
|
+
*
|
|
6
|
+
* `nil`/`none` mean "no border", but an *explicit* one overrides an inherited
|
|
7
|
+
* border (a table-level grid via `w:tblBorders`, a paragraph-style border, a
|
|
8
|
+
* section page border), so it must still round-trip as `<w:side w:val="nil"/>`.
|
|
9
|
+
* A `BorderSpec` only reaches here when the source set it or the user turned the
|
|
10
|
+
* border off, so emitting it is faithful, not noise — dropping it silently
|
|
11
|
+
* re-inherited the container default (e.g. hidden table gridlines reappeared as
|
|
12
|
+
* a full grid on reload). A `nil`/`none` side usually carries no
|
|
13
|
+
* size/color/space, but Word writes `w:sz="0" w:space="0" w:color="auto"` on a
|
|
14
|
+
* turned-off side; those are emitted when present so the value survives a
|
|
15
|
+
* save→parse round-trip and is not otherwise added.
|
|
16
|
+
*
|
|
17
|
+
* `style` and the color values come straight from the parsed DOCX (the parser
|
|
18
|
+
* casts `w:val`/`w:color` without validating the enum), so they are
|
|
19
|
+
* untrusted and are `escapeXml`'d before re-entering XML attributes; for valid
|
|
20
|
+
* documents these are enum/hex values, so escaping is a no-op.
|
|
21
|
+
*/
|
|
22
|
+
function serializeBorder(border, elementName) {
|
|
23
|
+
if (!border) return "";
|
|
24
|
+
const attrs = [`w:val="${escapeXml(border.style)}"`];
|
|
25
|
+
if (border.size !== void 0) attrs.push(`w:sz="${intAttr(border.size)}"`);
|
|
26
|
+
if (border.space !== void 0) attrs.push(`w:space="${intAttr(border.space)}"`);
|
|
27
|
+
if (border.color) {
|
|
28
|
+
if (border.color.auto) attrs.push("w:color=\"auto\"");
|
|
29
|
+
else if (border.color.rgb) attrs.push(`w:color="${escapeXml(border.color.rgb)}"`);
|
|
30
|
+
if (border.color.themeColor) attrs.push(`w:themeColor="${escapeXml(border.color.themeColor)}"`);
|
|
31
|
+
if (border.color.themeTint) attrs.push(`w:themeTint="${escapeXml(border.color.themeTint)}"`);
|
|
32
|
+
if (border.color.themeShade) attrs.push(`w:themeShade="${escapeXml(border.color.themeShade)}"`);
|
|
33
|
+
}
|
|
34
|
+
if (border.shadow) attrs.push("w:shadow=\"true\"");
|
|
35
|
+
if (border.frame) attrs.push("w:frame=\"true\"");
|
|
36
|
+
if (border.artRelationshipId) attrs.push(`w:id="${escapeXml(border.artRelationshipId)}"`);
|
|
37
|
+
if (border.topLeftArtRelationshipId) attrs.push(`w:topLeft="${escapeXml(border.topLeftArtRelationshipId)}"`);
|
|
38
|
+
if (border.topRightArtRelationshipId) attrs.push(`w:topRight="${escapeXml(border.topRightArtRelationshipId)}"`);
|
|
39
|
+
if (border.bottomLeftArtRelationshipId) attrs.push(`w:bottomLeft="${escapeXml(border.bottomLeftArtRelationshipId)}"`);
|
|
40
|
+
if (border.bottomRightArtRelationshipId) attrs.push(`w:bottomRight="${escapeXml(border.bottomRightArtRelationshipId)}"`);
|
|
41
|
+
return `<w:${elementName} ${attrs.join(" ")}/>`;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { serializeBorder };
|