@a3s-lab/office 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 +21 -0
- package/README.md +470 -0
- package/THIRD_PARTY_NOTICES.md +33 -0
- package/dist/0~1403.js +245 -0
- package/dist/0~152.js +94 -0
- package/dist/0~3539.js +1856 -0
- package/dist/0~3557.js +179 -0
- package/dist/0~3635.js +302 -0
- package/dist/0~4595.js +1162 -0
- package/dist/0~5050.js +308 -0
- package/dist/0~6552.js +787 -0
- package/dist/0~7048.js +2110 -0
- package/dist/0~7614.js +1037 -0
- package/dist/0~8155.js +299 -0
- package/dist/0~9445.js +283 -0
- package/dist/0~9512.js +743 -0
- package/dist/0~document-editor.js +10967 -0
- package/dist/0~markdown-editor.js +2260 -0
- package/dist/0~pdf-viewer.js +2156 -0
- package/dist/0~presentation-editor.js +8359 -0
- package/dist/0~rslib-runtime.js +27 -0
- package/dist/0~spreadsheet-editor.js +10388 -0
- package/dist/0~use-office-draft.js +46 -0
- package/dist/0~work-document-extensions.js +2470 -0
- package/dist/0~work-document-links.js +14 -0
- package/dist/0~work-document-model-codec.js +42 -0
- package/dist/0~work-document-page-color.js +11 -0
- package/dist/0~work-document-paragraph-formatting.js +425 -0
- package/dist/0~work-docx-bibliography.js +347 -0
- package/dist/0~work-docx-export.js +1151 -0
- package/dist/0~work-docx-import.js +3116 -0
- package/dist/0~work-docx-page-color.js +42 -0
- package/dist/0~work-office-diagnostics.js +1377 -0
- package/dist/0~work-pptx-export.js +1009 -0
- package/dist/0~work-pptx-import.js +1138 -0
- package/dist/0~work-presentation-charts.js +442 -0
- package/dist/0~work-presentation-transition.js +38 -0
- package/dist/0~work-presentation-visual-scale.js +38 -0
- package/dist/0~work-spreadsheet-formula-support.js +9 -0
- package/dist/1134.js +445 -0
- package/dist/4104.js +5786 -0
- package/dist/432.js +211 -0
- package/dist/4704.js +1364 -0
- package/dist/6489.js +182 -0
- package/dist/8715.js +3959 -0
- package/dist/8728.js +723 -0
- package/dist/9356.js +10 -0
- package/dist/core.d.ts +15 -0
- package/dist/core.js +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/internal/design-system/primitives/button/button.d.ts +9 -0
- package/dist/internal/design-system/primitives/button/icon-button.d.ts +7 -0
- package/dist/internal/design-system/primitives/dialog/dialog.d.ts +12 -0
- package/dist/internal/design-system/primitives/feedback/collection-state.d.ts +9 -0
- package/dist/internal/design-system/primitives/feedback/inline-notice.d.ts +10 -0
- package/dist/internal/design-system/primitives/feedback/state-view.d.ts +13 -0
- package/dist/internal/design-system/primitives/form/field.d.ts +19 -0
- package/dist/internal/design-system/primitives/index.d.ts +14 -0
- package/dist/internal/design-system/primitives/layout/split-handle.d.ts +17 -0
- package/dist/internal/design-system/primitives/navigation/segmented-control.d.ts +19 -0
- package/dist/internal/design-system/primitives/navigation/tab-navigation.d.ts +13 -0
- package/dist/internal/design-system/primitives/navigation/tabs.d.ts +21 -0
- package/dist/internal/design-system/primitives/overlay/dialog-focus-scope.d.ts +17 -0
- package/dist/internal/design-system/primitives/overlay/popover.d.ts +34 -0
- package/dist/internal/design-system/primitives/overlay/portal-root.d.ts +1 -0
- package/dist/internal/design-system/primitives/status/status-badge.d.ts +6 -0
- package/dist/internal/features/work/components/work-document-pages.d.ts +4 -0
- package/dist/internal/features/work/components/work-editor-agent-menus.d.ts +12 -0
- package/dist/internal/features/work/components/work-editor-loading-state.d.ts +3 -0
- package/dist/internal/features/work/editors/document-changes-panel.d.ts +9 -0
- package/dist/internal/features/work/editors/document-citation-source-form.d.ts +33 -0
- package/dist/internal/features/work/editors/document-citations-panel.d.ts +8 -0
- package/dist/internal/features/work/editors/document-columns-panel.d.ts +5 -0
- package/dist/internal/features/work/editors/document-comment-composer.d.ts +13 -0
- package/dist/internal/features/work/editors/document-comments-panel.d.ts +17 -0
- package/dist/internal/features/work/editors/document-editor-focus.d.ts +1 -0
- package/dist/internal/features/work/editors/document-editor-pagination.d.ts +3 -0
- package/dist/internal/features/work/editors/document-editor-support.d.ts +34 -0
- package/dist/internal/features/work/editors/document-editor.d.ts +20 -0
- package/dist/internal/features/work/editors/document-find-highlight.d.ts +8 -0
- package/dist/internal/features/work/editors/document-find-replace-panel.d.ts +10 -0
- package/dist/internal/features/work/editors/document-formatting-options.d.ts +113 -0
- package/dist/internal/features/work/editors/document-home-ribbon.d.ts +9 -0
- package/dist/internal/features/work/editors/document-layout-panel.d.ts +10 -0
- package/dist/internal/features/work/editors/document-list-gallery.d.ts +4 -0
- package/dist/internal/features/work/editors/document-navigation-panel.d.ts +9 -0
- package/dist/internal/features/work/editors/document-page-chrome-editor.d.ts +39 -0
- package/dist/internal/features/work/editors/document-page-chrome-panel.d.ts +5 -0
- package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +10 -0
- package/dist/internal/features/work/editors/document-page-navigation.d.ts +14 -0
- package/dist/internal/features/work/editors/document-page-stack.d.ts +8 -0
- package/dist/internal/features/work/editors/document-pagination-popover.d.ts +4 -0
- package/dist/internal/features/work/editors/document-paragraph-spacing-popover.d.ts +4 -0
- package/dist/internal/features/work/editors/document-picture-ribbon.d.ts +4 -0
- package/dist/internal/features/work/editors/document-ruler-tab-stops.d.ts +12 -0
- package/dist/internal/features/work/editors/document-ruler.d.ts +15 -0
- package/dist/internal/features/work/editors/document-selection-context-menu.d.ts +22 -0
- package/dist/internal/features/work/editors/document-selection-toolbar.d.ts +8 -0
- package/dist/internal/features/work/editors/document-status-bar.d.ts +19 -0
- package/dist/internal/features/work/editors/document-style-gallery.d.ts +4 -0
- package/dist/internal/features/work/editors/document-table-insert-popover.d.ts +4 -0
- package/dist/internal/features/work/editors/document-table-ribbon.d.ts +7 -0
- package/dist/internal/features/work/editors/document-task-pane.d.ts +11 -0
- package/dist/internal/features/work/editors/document-toolbar.d.ts +100 -0
- package/dist/internal/features/work/editors/document-vertical-ruler.d.ts +6 -0
- package/dist/internal/features/work/editors/markdown-editor-focus.d.ts +2 -0
- package/dist/internal/features/work/editors/markdown-editor.d.ts +16 -0
- package/dist/internal/features/work/editors/markdown-insert-dialog.d.ts +19 -0
- package/dist/internal/features/work/editors/markdown-selection-context-menu.d.ts +14 -0
- package/dist/internal/features/work/editors/markdown-source-commands.d.ts +41 -0
- package/dist/internal/features/work/editors/markdown-status.d.ts +7 -0
- package/dist/internal/features/work/editors/markdown-toolbar.d.ts +22 -0
- package/dist/internal/features/work/editors/markdown-workspace.d.ts +26 -0
- package/dist/internal/features/work/editors/office-checkbox.d.ts +9 -0
- package/dist/internal/features/work/editors/office-color-picker.d.ts +11 -0
- package/dist/internal/features/work/editors/office-controls.d.ts +7 -0
- package/dist/internal/features/work/editors/office-dialog.d.ts +35 -0
- package/dist/internal/features/work/editors/office-editor-extension.d.ts +86 -0
- package/dist/internal/features/work/editors/office-file-data.d.ts +1 -0
- package/dist/internal/features/work/editors/office-font-families.d.ts +187 -0
- package/dist/internal/features/work/editors/office-menu-keyboard.d.ts +2 -0
- package/dist/internal/features/work/editors/office-number-field.d.ts +21 -0
- package/dist/internal/features/work/editors/office-number-normalization.d.ts +9 -0
- package/dist/internal/features/work/editors/office-select.d.ts +19 -0
- package/dist/internal/features/work/editors/office-shortcuts.d.ts +1 -0
- package/dist/internal/features/work/editors/office-slider.d.ts +10 -0
- package/dist/internal/features/work/editors/office-table-dimensions.d.ts +4 -0
- package/dist/internal/features/work/editors/office-table-insert-popover.d.ts +7 -0
- package/dist/internal/features/work/editors/office-task-pane.d.ts +7 -0
- package/dist/internal/features/work/editors/office-text-field.d.ts +20 -0
- package/dist/internal/features/work/editors/office-tiptap-extensions.d.ts +2 -0
- package/dist/internal/features/work/editors/pdf-annotation-controller.d.ts +23 -0
- package/dist/internal/features/work/editors/pdf-editor-extensions.d.ts +36 -0
- package/dist/internal/features/work/editors/pdf-thumbnail-rail.d.ts +26 -0
- package/dist/internal/features/work/editors/pdf-toolbar.d.ts +23 -0
- package/dist/internal/features/work/editors/pdf-viewer-controller.d.ts +48 -0
- package/dist/internal/features/work/editors/pdf-viewer.d.ts +11 -0
- package/dist/internal/features/work/editors/presentation-arrangement-controller.d.ts +19 -0
- package/dist/internal/features/work/editors/presentation-chart-analysis-canvas.d.ts +21 -0
- package/dist/internal/features/work/editors/presentation-chart-axis-canvas.d.ts +33 -0
- package/dist/internal/features/work/editors/presentation-chart-axis-editor.d.ts +5 -0
- package/dist/internal/features/work/editors/presentation-chart-canvas.d.ts +5 -0
- package/dist/internal/features/work/editors/presentation-chart-cartesian-canvas.d.ts +3 -0
- package/dist/internal/features/work/editors/presentation-chart-data-label-editor.d.ts +6 -0
- package/dist/internal/features/work/editors/presentation-chart-data-labels.d.ts +26 -0
- package/dist/internal/features/work/editors/presentation-chart-layout-editor.d.ts +5 -0
- package/dist/internal/features/work/editors/presentation-chart-legend-canvas.d.ts +15 -0
- package/dist/internal/features/work/editors/presentation-chart-panel.d.ts +7 -0
- package/dist/internal/features/work/editors/presentation-chart-series-analysis-editor.d.ts +6 -0
- package/dist/internal/features/work/editors/presentation-chart-series-canvas.d.ts +15 -0
- package/dist/internal/features/work/editors/presentation-command-controller.d.ts +3 -0
- package/dist/internal/features/work/editors/presentation-command-types.d.ts +206 -0
- package/dist/internal/features/work/editors/presentation-comments-panel.d.ts +9 -0
- package/dist/internal/features/work/editors/presentation-context-menu.d.ts +11 -0
- package/dist/internal/features/work/editors/presentation-design-panel.d.ts +13 -0
- package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +12 -0
- package/dist/internal/features/work/editors/presentation-editor-operations.d.ts +10 -0
- package/dist/internal/features/work/editors/presentation-editor-types.d.ts +22 -0
- package/dist/internal/features/work/editors/presentation-editor.d.ts +3 -0
- package/dist/internal/features/work/editors/presentation-keyboard-extension.d.ts +3 -0
- package/dist/internal/features/work/editors/presentation-player.d.ts +7 -0
- package/dist/internal/features/work/editors/presentation-presenter-view.d.ts +15 -0
- package/dist/internal/features/work/editors/presentation-selection.d.ts +21 -0
- package/dist/internal/features/work/editors/presentation-slide-canvas.d.ts +26 -0
- package/dist/internal/features/work/editors/presentation-slide-thumbnail.d.ts +18 -0
- package/dist/internal/features/work/editors/presentation-status-bar.d.ts +10 -0
- package/dist/internal/features/work/editors/presentation-text-editor.d.ts +22 -0
- package/dist/internal/features/work/editors/presentation-text-formatting.d.ts +3 -0
- package/dist/internal/features/work/editors/presentation-thumbnail-rail.d.ts +20 -0
- package/dist/internal/features/work/editors/presentation-toolbar.d.ts +19 -0
- package/dist/internal/features/work/editors/presentation-transition-panel.d.ts +9 -0
- package/dist/internal/features/work/editors/presentation-workspace.d.ts +38 -0
- package/dist/internal/features/work/editors/spreadsheet-calculation-model.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-calculation-projection.d.ts +32 -0
- package/dist/internal/features/work/editors/spreadsheet-chart-axis-editor.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-chart-draft.d.ts +17 -0
- package/dist/internal/features/work/editors/spreadsheet-chart-layout-editor.d.ts +13 -0
- package/dist/internal/features/work/editors/spreadsheet-chart-panel.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-chart-series-style-editor.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-clipboard-shortcuts.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +121 -0
- package/dist/internal/features/work/editors/spreadsheet-conditional-comparison-fields.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-conditional-format-model.d.ts +72 -0
- package/dist/internal/features/work/editors/spreadsheet-conditional-format-panel.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-conditional-threshold-fields.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-context-menu.d.ts +36 -0
- package/dist/internal/features/work/editors/spreadsheet-data-label-editor.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +46 -0
- package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +31 -0
- package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +16 -0
- package/dist/internal/features/work/editors/spreadsheet-error-bar-editor.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-find-bar.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-find.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-formula-panel.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-header-footer-fields.d.ts +5 -0
- package/dist/internal/features/work/editors/spreadsheet-keyboard-navigation.d.ts +18 -0
- package/dist/internal/features/work/editors/spreadsheet-number-format.d.ts +11 -0
- package/dist/internal/features/work/editors/spreadsheet-pivot-panel.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-print-settings-panel.d.ts +6 -0
- package/dist/internal/features/work/editors/spreadsheet-protection-panel.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-sheet-bar.d.ts +17 -0
- package/dist/internal/features/work/editors/spreadsheet-sheet-model.d.ts +13 -0
- package/dist/internal/features/work/editors/spreadsheet-trendline-editor.d.ts +8 -0
- package/dist/internal/features/work/editors/spreadsheet-workbook-panel.d.ts +16 -0
- package/dist/internal/features/work/editors/use-document-comments.d.ts +26 -0
- package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +19 -0
- package/dist/internal/features/work/editors/use-document-layout-fonts.d.ts +2 -0
- package/dist/internal/features/work/editors/use-document-page-chrome.d.ts +33 -0
- package/dist/internal/features/work/editors/use-document-pagination.d.ts +46 -0
- package/dist/internal/features/work/editors/use-markdown-source-history.d.ts +16 -0
- package/dist/internal/features/work/editors/use-office-draft.d.ts +10 -0
- package/dist/internal/features/work/editors/use-office-editor-keyboard-shortcuts.d.ts +9 -0
- package/dist/internal/features/work/editors/use-office-editor-runtime.d.ts +6 -0
- package/dist/internal/features/work/editors/use-office-editor-wheel-zoom.d.ts +19 -0
- package/dist/internal/features/work/editors/use-office-history.d.ts +10 -0
- package/dist/internal/features/work/editors/use-presentation-clipboard.d.ts +22 -0
- package/dist/internal/features/work/editors/use-presentation-design-commands.d.ts +33 -0
- package/dist/internal/features/work/editors/use-presentation-element-commands.d.ts +29 -0
- package/dist/internal/features/work/editors/use-presentation-geometry.d.ts +17 -0
- package/dist/internal/features/work/editors/use-presentation-history.d.ts +12 -0
- package/dist/internal/features/work/editors/use-presentation-review-commands.d.ts +22 -0
- package/dist/internal/features/work/editors/use-presentation-selection.d.ts +11 -0
- package/dist/internal/features/work/editors/use-presentation-slide-commands.d.ts +18 -0
- package/dist/internal/features/work/editors/use-presentation-thumbnail-visibility.d.ts +4 -0
- package/dist/internal/features/work/editors/use-presentation-thumbnail-window.d.ts +17 -0
- package/dist/internal/features/work/editors/use-presentation-transform.d.ts +53 -0
- package/dist/internal/features/work/editors/use-spreadsheet-calculation.d.ts +17 -0
- package/dist/internal/features/work/editors/use-spreadsheet-workbook-sync.d.ts +10 -0
- package/dist/internal/features/work/editors/work-office-chrome.d.ts +61 -0
- package/dist/internal/features/work/editors/work-office-ribbon-overflow.d.ts +18 -0
- package/dist/internal/features/work/work-agent-proposal-apply.d.ts +8 -0
- package/dist/internal/features/work/work-agent-proposal.d.ts +55 -0
- package/dist/internal/features/work/work-agent-request.d.ts +6 -0
- package/dist/internal/features/work/work-chart-series-analysis-context.d.ts +3 -0
- package/dist/internal/features/work/work-document-caption-nodes.d.ts +13 -0
- package/dist/internal/features/work/work-document-captions.d.ts +14 -0
- package/dist/internal/features/work/work-document-changes.d.ts +35 -0
- package/dist/internal/features/work/work-document-character-formatting.d.ts +13 -0
- package/dist/internal/features/work/work-document-citation-nodes.d.ts +25 -0
- package/dist/internal/features/work/work-document-citations.d.ts +21 -0
- package/dist/internal/features/work/work-document-columns.d.ts +15 -0
- package/dist/internal/features/work/work-document-comments.d.ts +48 -0
- package/dist/internal/features/work/work-document-extensions.d.ts +11 -0
- package/dist/internal/features/work/work-document-field-node.d.ts +12 -0
- package/dist/internal/features/work/work-document-fields.d.ts +15 -0
- package/dist/internal/features/work/work-document-file-io.d.ts +4 -0
- package/dist/internal/features/work/work-document-fonts.d.ts +16 -0
- package/dist/internal/features/work/work-document-image-layout.d.ts +29 -0
- package/dist/internal/features/work/work-document-incremental-layout.d.ts +17 -0
- package/dist/internal/features/work/work-document-layout.d.ts +5 -0
- package/dist/internal/features/work/work-document-line-measurement.d.ts +24 -0
- package/dist/internal/features/work/work-document-links.d.ts +2 -0
- package/dist/internal/features/work/work-document-lists.d.ts +25 -0
- package/dist/internal/features/work/work-document-model-codec.d.ts +3 -0
- package/dist/internal/features/work/work-document-model.d.ts +12 -0
- package/dist/internal/features/work/work-document-note-nodes.d.ts +11 -0
- package/dist/internal/features/work/work-document-notes.d.ts +18 -0
- package/dist/internal/features/work/work-document-outline.d.ts +14 -0
- package/dist/internal/features/work/work-document-page-break.d.ts +2 -0
- package/dist/internal/features/work/work-document-page-chrome-commands.d.ts +15 -0
- package/dist/internal/features/work/work-document-page-chrome.d.ts +19 -0
- package/dist/internal/features/work/work-document-page-color.d.ts +3 -0
- package/dist/internal/features/work/work-document-pages.d.ts +19 -0
- package/dist/internal/features/work/work-document-pagination-decorations.d.ts +3 -0
- package/dist/internal/features/work/work-document-pagination-dom.d.ts +35 -0
- package/dist/internal/features/work/work-document-pagination-measurement.d.ts +9 -0
- package/dist/internal/features/work/work-document-pagination-types.d.ts +88 -0
- package/dist/internal/features/work/work-document-pagination.d.ts +17 -0
- package/dist/internal/features/work/work-document-paragraph-formatting.d.ts +61 -0
- package/dist/internal/features/work/work-document-search.d.ts +11 -0
- package/dist/internal/features/work/work-document-section-editor.d.ts +20 -0
- package/dist/internal/features/work/work-document-section-node.d.ts +13 -0
- package/dist/internal/features/work/work-document-section.d.ts +34 -0
- package/dist/internal/features/work/work-document-selection-menu.d.ts +54 -0
- package/dist/internal/features/work/work-document-tab-node.d.ts +6 -0
- package/dist/internal/features/work/work-document-tab-stops.d.ts +29 -0
- package/dist/internal/features/work/work-document-table-cell-formatting.d.ts +46 -0
- package/dist/internal/features/work/work-document-table-commands.d.ts +17 -0
- package/dist/internal/features/work/work-document-table-pagination.d.ts +5 -0
- package/dist/internal/features/work/work-document-table-row.d.ts +37 -0
- package/dist/internal/features/work/work-document-table-sizing.d.ts +27 -0
- package/dist/internal/features/work/work-document-text-layout.d.ts +14 -0
- package/dist/internal/features/work/work-docx-bibliography.d.ts +12 -0
- package/dist/internal/features/work/work-docx-caption-diagnostics.d.ts +6 -0
- package/dist/internal/features/work/work-docx-caption-export.d.ts +4 -0
- package/dist/internal/features/work/work-docx-caption-fields.d.ts +5 -0
- package/dist/internal/features/work/work-docx-caption-import.d.ts +20 -0
- package/dist/internal/features/work/work-docx-change-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-citation-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-citation-export.d.ts +3 -0
- package/dist/internal/features/work/work-docx-citation-import.d.ts +23 -0
- package/dist/internal/features/work/work-docx-column-export.d.ts +14 -0
- package/dist/internal/features/work/work-docx-column-import.d.ts +2 -0
- package/dist/internal/features/work/work-docx-comment-import.d.ts +14 -0
- package/dist/internal/features/work/work-docx-export-formatting.d.ts +30 -0
- package/dist/internal/features/work/work-docx-export-image.d.ts +2 -0
- package/dist/internal/features/work/work-docx-export.d.ts +2 -0
- package/dist/internal/features/work/work-docx-field-export.d.ts +2 -0
- package/dist/internal/features/work/work-docx-field-import.d.ts +16 -0
- package/dist/internal/features/work/work-docx-field-instructions.d.ts +8 -0
- package/dist/internal/features/work/work-docx-image-layout-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-import.d.ts +50 -0
- package/dist/internal/features/work/work-docx-list-import.d.ts +14 -0
- package/dist/internal/features/work/work-docx-note-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-note-import.d.ts +3 -0
- package/dist/internal/features/work/work-docx-page-chrome-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-page-chrome-import.d.ts +11 -0
- package/dist/internal/features/work/work-docx-page-color.d.ts +2 -0
- package/dist/internal/features/work/work-docx-paragraph-alignment-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-paragraph-direction-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-paragraph-indent-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-paragraph-spacing-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-paragraph-styles.d.ts +18 -0
- package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +19 -0
- package/dist/internal/features/work/work-docx-tab-stop-import.d.ts +13 -0
- package/dist/internal/features/work/work-docx-table-cell-export.d.ts +4 -0
- package/dist/internal/features/work/work-docx-table-cell-import.d.ts +16 -0
- package/dist/internal/features/work/work-docx-table-row-import.d.ts +13 -0
- package/dist/internal/features/work/work-docx-table-sizing-export.d.ts +8 -0
- package/dist/internal/features/work/work-docx-table-sizing-import.d.ts +12 -0
- package/dist/internal/features/work/work-docx-theme.d.ts +9 -0
- package/dist/internal/features/work/work-file-data.d.ts +1 -0
- package/dist/internal/features/work/work-file-download.d.ts +3 -0
- package/dist/internal/features/work/work-file-io.d.ts +8 -0
- package/dist/internal/features/work/work-markdown-extensions.d.ts +19 -0
- package/dist/internal/features/work/work-markdown-file-io.d.ts +3 -0
- package/dist/internal/features/work/work-markdown-selection-menu.d.ts +57 -0
- package/dist/internal/features/work/work-office-diagnostics.d.ts +9 -0
- package/dist/internal/features/work/work-ooxml-package.d.ts +28 -0
- package/dist/internal/features/work/work-pdf-export.d.ts +23 -0
- package/dist/internal/features/work/work-pptx-chart-axes.d.ts +3 -0
- package/dist/internal/features/work/work-pptx-chart-axis-diagnostics.d.ts +5 -0
- package/dist/internal/features/work/work-pptx-chart-data-labels.d.ts +12 -0
- package/dist/internal/features/work/work-pptx-chart-import.d.ts +11 -0
- package/dist/internal/features/work/work-pptx-chart-layout-style.d.ts +15 -0
- package/dist/internal/features/work/work-pptx-chart-series-analysis.d.ts +13 -0
- package/dist/internal/features/work/work-pptx-chart-xy.d.ts +3 -0
- package/dist/internal/features/work/work-pptx-comments.d.ts +17 -0
- package/dist/internal/features/work/work-pptx-export.d.ts +4 -0
- package/dist/internal/features/work/work-pptx-groups.d.ts +19 -0
- package/dist/internal/features/work/work-pptx-import.d.ts +6 -0
- package/dist/internal/features/work/work-pptx-layout-export.d.ts +13 -0
- package/dist/internal/features/work/work-pptx-layout-import.d.ts +30 -0
- package/dist/internal/features/work/work-pptx-style.d.ts +13 -0
- package/dist/internal/features/work/work-pptx-transition.d.ts +13 -0
- package/dist/internal/features/work/work-presentation-agent-context.d.ts +6 -0
- package/dist/internal/features/work/work-presentation-chart-axes.d.ts +14 -0
- package/dist/internal/features/work/work-presentation-charts.d.ts +37 -0
- package/dist/internal/features/work/work-presentation-clipboard.d.ts +26 -0
- package/dist/internal/features/work/work-presentation-file-io.d.ts +15 -0
- package/dist/internal/features/work/work-presentation-groups.d.ts +17 -0
- package/dist/internal/features/work/work-presentation-layouts.d.ts +13 -0
- package/dist/internal/features/work/work-presentation-transition.d.ts +4 -0
- package/dist/internal/features/work/work-presentation-visual-scale.d.ts +2 -0
- package/dist/internal/features/work/work-repository.d.ts +4 -0
- package/dist/internal/features/work/work-spreadsheet-agent-context.d.ts +15 -0
- package/dist/internal/features/work/work-spreadsheet-chart-axis.d.ts +42 -0
- package/dist/internal/features/work/work-spreadsheet-chart-layout.d.ts +29 -0
- package/dist/internal/features/work/work-spreadsheet-chart-legend-svg.d.ts +18 -0
- package/dist/internal/features/work/work-spreadsheet-chart-series-layout.d.ts +24 -0
- package/dist/internal/features/work/work-spreadsheet-chart-series-style.d.ts +29 -0
- package/dist/internal/features/work/work-spreadsheet-chart-svg-utils.d.ts +7 -0
- package/dist/internal/features/work/work-spreadsheet-chart-svg.d.ts +3 -0
- package/dist/internal/features/work/work-spreadsheet-chart-types.d.ts +147 -0
- package/dist/internal/features/work/work-spreadsheet-chart-validation.d.ts +2 -0
- package/dist/internal/features/work/work-spreadsheet-charts.d.ts +17 -0
- package/dist/internal/features/work/work-spreadsheet-combination-chart-svg.d.ts +9 -0
- package/dist/internal/features/work/work-spreadsheet-comments.d.ts +7 -0
- package/dist/internal/features/work/work-spreadsheet-conditional-canvas.d.ts +5 -0
- package/dist/internal/features/work/work-spreadsheet-conditional-colors.d.ts +9 -0
- package/dist/internal/features/work/work-spreadsheet-conditional-comparisons.d.ts +4 -0
- package/dist/internal/features/work/work-spreadsheet-conditional-data-bar.d.ts +8 -0
- package/dist/internal/features/work/work-spreadsheet-conditional-format.d.ts +10 -0
- package/dist/internal/features/work/work-spreadsheet-conditional-icons.d.ts +107 -0
- package/dist/internal/features/work/work-spreadsheet-conditional-values.d.ts +19 -0
- package/dist/internal/features/work/work-spreadsheet-data-label-svg.d.ts +27 -0
- package/dist/internal/features/work/work-spreadsheet-error-bar-svg.d.ts +5 -0
- package/dist/internal/features/work/work-spreadsheet-error-bars.d.ts +8 -0
- package/dist/internal/features/work/work-spreadsheet-formula-analysis.d.ts +30 -0
- package/dist/internal/features/work/work-spreadsheet-formula-support.d.ts +1 -0
- package/dist/internal/features/work/work-spreadsheet-formulas.d.ts +19 -0
- package/dist/internal/features/work/work-spreadsheet-header-footer.d.ts +14 -0
- package/dist/internal/features/work/work-spreadsheet-line-chart-svg.d.ts +10 -0
- package/dist/internal/features/work/work-spreadsheet-page-breaks.d.ts +4 -0
- package/dist/internal/features/work/work-spreadsheet-page-setup.d.ts +26 -0
- package/dist/internal/features/work/work-spreadsheet-pivot-engine.d.ts +21 -0
- package/dist/internal/features/work/work-spreadsheet-pivot-values.d.ts +7 -0
- package/dist/internal/features/work/work-spreadsheet-pivots.d.ts +27 -0
- package/dist/internal/features/work/work-spreadsheet-protection.d.ts +55 -0
- package/dist/internal/features/work/work-spreadsheet-ranges.d.ts +25 -0
- package/dist/internal/features/work/work-spreadsheet-trendline-svg.d.ts +9 -0
- package/dist/internal/features/work/work-spreadsheet-trendlines.d.ts +11 -0
- package/dist/internal/features/work/work-spreadsheet-xy-chart-axes-svg.d.ts +10 -0
- package/dist/internal/features/work/work-templates.d.ts +4 -0
- package/dist/internal/features/work/work-types.d.ts +513 -0
- package/dist/internal/features/work/work-xlsx-chart-axes.d.ts +4 -0
- package/dist/internal/features/work/work-xlsx-chart-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-xlsx-chart-layout.d.ts +16 -0
- package/dist/internal/features/work/work-xlsx-chart-series-style.d.ts +6 -0
- package/dist/internal/features/work/work-xlsx-chart-values.d.ts +10 -0
- package/dist/internal/features/work/work-xlsx-charts.d.ts +32 -0
- package/dist/internal/features/work/work-xlsx-conditional-format-diagnostics.d.ts +6 -0
- package/dist/internal/features/work/work-xlsx-conditional-format-write.d.ts +11 -0
- package/dist/internal/features/work/work-xlsx-conditional-format.d.ts +29 -0
- package/dist/internal/features/work/work-xlsx-defined-names.d.ts +4 -0
- package/dist/internal/features/work/work-xlsx-drawing-geometry.d.ts +27 -0
- package/dist/internal/features/work/work-xlsx-formula-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-xlsx-formulas.d.ts +40 -0
- package/dist/internal/features/work/work-xlsx-header-footer.d.ts +12 -0
- package/dist/internal/features/work/work-xlsx-images.d.ts +17 -0
- package/dist/internal/features/work/work-xlsx-interop.d.ts +39 -0
- package/dist/internal/features/work/work-xlsx-page-breaks.d.ts +7 -0
- package/dist/internal/features/work/work-xlsx-page-setup-diagnostics.d.ts +2 -0
- package/dist/internal/features/work/work-xlsx-page-setup.d.ts +5 -0
- package/dist/internal/features/work/work-xlsx-pivot-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-xlsx-pivot-xml.d.ts +9 -0
- package/dist/internal/features/work/work-xlsx-pivots.d.ts +32 -0
- package/dist/internal/features/work/work-xlsx-protection.d.ts +24 -0
- package/dist/internal/features/workspace/components/workspace-context-menu.d.ts +29 -0
- package/dist/internal/features/workspace/components/workspace-text-control-selection.d.ts +7 -0
- package/dist/internal/kernel/office-kernel-client-types.d.ts +40 -0
- package/dist/internal/kernel/office-kernel-client.d.ts +4 -0
- package/dist/internal/kernel/office-kernel-fallback.d.ts +2 -0
- package/dist/internal/kernel/office-kernel-presentation-fallback.d.ts +2 -0
- package/dist/internal/kernel/office-kernel-protocol.d.ts +229 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-fallback-formula.d.ts +3 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-fallback-validation.d.ts +5 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-fallback-value.d.ts +6 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-fallback.d.ts +2 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-protocol.d.ts +112 -0
- package/dist/internal/kernel/office-kernel-spreadsheet-session-fallback.d.ts +8 -0
- package/dist/internal/kernel/office-kernel-text-fallback.d.ts +10 -0
- package/dist/internal/kernel/office-kernel-version.d.ts +1 -0
- package/dist/internal/kernel/office-kernel.worker.d.ts +1 -0
- package/dist/internal/keyboard-shortcuts.d.ts +2 -0
- package/dist/internal/state/app-state.d.ts +8 -0
- package/dist/noto-naskh-arabic-regular.ttf +0 -0
- package/dist/noto-naskh-arabic.LICENSE.txt +94 -0
- package/dist/noto-sans-hans-regular.otf +0 -0
- package/dist/noto-sans-hans.LICENSE.txt +94 -0
- package/dist/noto-sans-hebrew-regular.ttf +0 -0
- package/dist/noto-sans-hebrew.LICENSE.txt +94 -0
- package/dist/noto-sans-regular.ttf +0 -0
- package/dist/noto-sans.LICENSE.txt +94 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/office-kernel.worker.js +14605 -0
- package/dist/office-surface.d.ts +10 -0
- package/dist/pdfium.LICENSE.txt +196 -0
- package/dist/pdfium.wasm +0 -0
- package/dist/pptxgen.LICENSE.txt +21 -0
- package/dist/pptxgen.bundle.js +11244 -0
- package/dist/react.d.ts +51 -0
- package/dist/react.js +1 -0
- package/dist/styles.css +17435 -0
- package/dist/styles.js +0 -0
- package/dist/vue.d.ts +282 -0
- package/dist/vue.js +231 -0
- package/dist/web-component.d.ts +98 -0
- package/dist/web-component.js +335 -0
- package/docs/browser-editor-architecture.md +947 -0
- package/package.json +165 -0
package/dist/0~7048.js
ADDED
|
@@ -0,0 +1,2110 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
3
|
+
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
|
4
|
+
import { Dialog } from "./0~4595.js";
|
|
5
|
+
import { button_Button, office_text_field_OfficeTextField, office_text_field_OfficeTextArea } from "./0~9512.js";
|
|
6
|
+
function CollectionState({ children, icon, actions, tone = 'neutral', role, className = '' }) {
|
|
7
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
8
|
+
className: `ds-collection-state ${tone}${className ? ` ${className}` : ''}`,
|
|
9
|
+
role: role,
|
|
10
|
+
children: [
|
|
11
|
+
icon && /*#__PURE__*/ jsx("span", {
|
|
12
|
+
className: "ds-collection-state-icon",
|
|
13
|
+
"aria-hidden": "true",
|
|
14
|
+
children: icon
|
|
15
|
+
}),
|
|
16
|
+
/*#__PURE__*/ jsx("span", {
|
|
17
|
+
children: children
|
|
18
|
+
}),
|
|
19
|
+
actions && /*#__PURE__*/ jsx("span", {
|
|
20
|
+
className: "ds-collection-state-actions",
|
|
21
|
+
children: actions
|
|
22
|
+
})
|
|
23
|
+
]
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const ACTIVE_OVERLAY_SELECTOR = '.ds-dialog-backdrop, .ds-popover.open, [role="menu"]';
|
|
27
|
+
const ESCAPE_CONSUMER_SELECTOR = '[data-office-escape-consumer="true"]';
|
|
28
|
+
const OFFICE_TASK_PANE_MODAL_QUERY = '(max-width: 900px)';
|
|
29
|
+
function officeTaskPaneOwnsEscape(event) {
|
|
30
|
+
return 'Escape' === event.key && !event.defaultPrevented && !(event.target instanceof Element && event.target.closest(ESCAPE_CONSUMER_SELECTOR)) && !document.querySelector(ACTIVE_OVERLAY_SELECTOR);
|
|
31
|
+
}
|
|
32
|
+
function handleOfficeTaskPaneKeyDown(event, onClose) {
|
|
33
|
+
if (!officeTaskPaneOwnsEscape(event.nativeEvent)) return;
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
event.stopPropagation();
|
|
36
|
+
onClose();
|
|
37
|
+
}
|
|
38
|
+
function useOfficeTaskPaneEscape(active, onClose) {
|
|
39
|
+
useEffect(()=>{
|
|
40
|
+
if (!active) return;
|
|
41
|
+
const closeFromEscape = (event)=>{
|
|
42
|
+
if (!officeTaskPaneOwnsEscape(event)) return;
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
event.stopPropagation();
|
|
45
|
+
onClose();
|
|
46
|
+
};
|
|
47
|
+
document.addEventListener('keydown', closeFromEscape, true);
|
|
48
|
+
return ()=>document.removeEventListener('keydown', closeFromEscape, true);
|
|
49
|
+
}, [
|
|
50
|
+
active,
|
|
51
|
+
onClose
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
function useOfficeTaskPaneModal() {
|
|
55
|
+
const [matches, setMatches] = useState(officeTaskPaneModalMatches);
|
|
56
|
+
useEffect(()=>{
|
|
57
|
+
if ("u" < typeof window || 'function' != typeof window.matchMedia) return;
|
|
58
|
+
const mediaQuery = window.matchMedia(OFFICE_TASK_PANE_MODAL_QUERY);
|
|
59
|
+
const update = ()=>setMatches(mediaQuery.matches);
|
|
60
|
+
update();
|
|
61
|
+
if ('function' == typeof mediaQuery.addEventListener) {
|
|
62
|
+
mediaQuery.addEventListener('change', update);
|
|
63
|
+
return ()=>mediaQuery.removeEventListener('change', update);
|
|
64
|
+
}
|
|
65
|
+
mediaQuery.addListener(update);
|
|
66
|
+
return ()=>mediaQuery.removeListener(update);
|
|
67
|
+
}, []);
|
|
68
|
+
return matches;
|
|
69
|
+
}
|
|
70
|
+
function officeTaskPaneModalMatches() {
|
|
71
|
+
if ("u" < typeof window || 'function' != typeof window.matchMedia) return false;
|
|
72
|
+
return window.matchMedia(OFFICE_TASK_PANE_MODAL_QUERY).matches;
|
|
73
|
+
}
|
|
74
|
+
function useOfficeDialog() {
|
|
75
|
+
const [request, setRequest] = useState(null);
|
|
76
|
+
const sequence = useRef(0);
|
|
77
|
+
const promptResolver = useRef(null);
|
|
78
|
+
const noticeResolver = useRef(null);
|
|
79
|
+
const confirmResolver = useRef(null);
|
|
80
|
+
const invokerRef = useRef(null);
|
|
81
|
+
const releaseInvokerTimer = useRef(null);
|
|
82
|
+
const promptFieldId = useId();
|
|
83
|
+
const retainInvoker = useCallback(()=>{
|
|
84
|
+
if (null !== releaseInvokerTimer.current) window.clearTimeout(releaseInvokerTimer.current);
|
|
85
|
+
releaseInvokerTimer.current = null;
|
|
86
|
+
if (!invokerRef.current?.isConnected) invokerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
87
|
+
}, []);
|
|
88
|
+
const releaseInvoker = useCallback(()=>{
|
|
89
|
+
if (null !== releaseInvokerTimer.current) window.clearTimeout(releaseInvokerTimer.current);
|
|
90
|
+
releaseInvokerTimer.current = window.setTimeout(()=>{
|
|
91
|
+
invokerRef.current = null;
|
|
92
|
+
releaseInvokerTimer.current = null;
|
|
93
|
+
}, 0);
|
|
94
|
+
}, []);
|
|
95
|
+
const closePrompt = useCallback((value)=>{
|
|
96
|
+
promptResolver.current?.(value);
|
|
97
|
+
promptResolver.current = null;
|
|
98
|
+
setRequest(null);
|
|
99
|
+
releaseInvoker();
|
|
100
|
+
}, [
|
|
101
|
+
releaseInvoker
|
|
102
|
+
]);
|
|
103
|
+
const closeNotice = useCallback(()=>{
|
|
104
|
+
noticeResolver.current?.();
|
|
105
|
+
noticeResolver.current = null;
|
|
106
|
+
setRequest(null);
|
|
107
|
+
releaseInvoker();
|
|
108
|
+
}, [
|
|
109
|
+
releaseInvoker
|
|
110
|
+
]);
|
|
111
|
+
const closeConfirm = useCallback((confirmed)=>{
|
|
112
|
+
confirmResolver.current?.(confirmed);
|
|
113
|
+
confirmResolver.current = null;
|
|
114
|
+
setRequest(null);
|
|
115
|
+
releaseInvoker();
|
|
116
|
+
}, [
|
|
117
|
+
releaseInvoker
|
|
118
|
+
]);
|
|
119
|
+
const prompt = useCallback((options)=>new Promise((resolve)=>{
|
|
120
|
+
retainInvoker();
|
|
121
|
+
promptResolver.current?.(null);
|
|
122
|
+
noticeResolver.current?.();
|
|
123
|
+
confirmResolver.current?.(false);
|
|
124
|
+
promptResolver.current = resolve;
|
|
125
|
+
noticeResolver.current = null;
|
|
126
|
+
confirmResolver.current = null;
|
|
127
|
+
setRequest({
|
|
128
|
+
id: ++sequence.current,
|
|
129
|
+
kind: 'prompt',
|
|
130
|
+
title: options.title,
|
|
131
|
+
description: options.description,
|
|
132
|
+
value: options.initialValue ?? '',
|
|
133
|
+
fieldLabel: options.fieldLabel ?? options.title,
|
|
134
|
+
placeholder: options.placeholder,
|
|
135
|
+
multiline: options.multiline,
|
|
136
|
+
inputMode: options.inputMode,
|
|
137
|
+
confirmLabel: options.confirmLabel ?? '确定',
|
|
138
|
+
requiredMessage: true === options.required ? '请填写此项。' : 'string' == typeof options.required ? options.required : void 0,
|
|
139
|
+
validate: options.validate,
|
|
140
|
+
restoreFocusTarget: options.restoreFocusTarget,
|
|
141
|
+
touched: false
|
|
142
|
+
});
|
|
143
|
+
}), [
|
|
144
|
+
retainInvoker
|
|
145
|
+
]);
|
|
146
|
+
const notice = useCallback((options)=>new Promise((resolve)=>{
|
|
147
|
+
retainInvoker();
|
|
148
|
+
promptResolver.current?.(null);
|
|
149
|
+
noticeResolver.current?.();
|
|
150
|
+
confirmResolver.current?.(false);
|
|
151
|
+
promptResolver.current = null;
|
|
152
|
+
noticeResolver.current = resolve;
|
|
153
|
+
confirmResolver.current = null;
|
|
154
|
+
setRequest({
|
|
155
|
+
id: ++sequence.current,
|
|
156
|
+
kind: 'notice',
|
|
157
|
+
title: options.title,
|
|
158
|
+
description: options.description,
|
|
159
|
+
confirmLabel: options.confirmLabel ?? '知道了',
|
|
160
|
+
restoreFocusTarget: options.restoreFocusTarget
|
|
161
|
+
});
|
|
162
|
+
}), [
|
|
163
|
+
retainInvoker
|
|
164
|
+
]);
|
|
165
|
+
const confirm = useCallback((options)=>new Promise((resolve)=>{
|
|
166
|
+
retainInvoker();
|
|
167
|
+
promptResolver.current?.(null);
|
|
168
|
+
noticeResolver.current?.();
|
|
169
|
+
confirmResolver.current?.(false);
|
|
170
|
+
promptResolver.current = null;
|
|
171
|
+
noticeResolver.current = null;
|
|
172
|
+
confirmResolver.current = resolve;
|
|
173
|
+
setRequest({
|
|
174
|
+
id: ++sequence.current,
|
|
175
|
+
kind: 'confirm',
|
|
176
|
+
title: options.title,
|
|
177
|
+
description: options.description,
|
|
178
|
+
confirmLabel: options.confirmLabel ?? '继续',
|
|
179
|
+
cancelLabel: options.cancelLabel ?? '取消',
|
|
180
|
+
confirmTone: options.confirmTone ?? 'primary',
|
|
181
|
+
restoreFocusTarget: options.restoreFocusTarget
|
|
182
|
+
});
|
|
183
|
+
}), [
|
|
184
|
+
retainInvoker
|
|
185
|
+
]);
|
|
186
|
+
useEffect(()=>()=>{
|
|
187
|
+
promptResolver.current?.(null);
|
|
188
|
+
noticeResolver.current?.();
|
|
189
|
+
confirmResolver.current?.(false);
|
|
190
|
+
if (null !== releaseInvokerTimer.current) window.clearTimeout(releaseInvokerTimer.current);
|
|
191
|
+
}, []);
|
|
192
|
+
const promptError = request?.kind === 'prompt' ? promptValidationMessage(request) : null;
|
|
193
|
+
const visiblePromptError = request?.kind === 'prompt' && request.touched ? promptError : null;
|
|
194
|
+
const submitPrompt = ()=>{
|
|
195
|
+
if (!request || 'prompt' !== request.kind) return;
|
|
196
|
+
if (promptValidationMessage(request)) return void setRequest({
|
|
197
|
+
...request,
|
|
198
|
+
touched: true
|
|
199
|
+
});
|
|
200
|
+
closePrompt(request.value);
|
|
201
|
+
};
|
|
202
|
+
const dialog = request ? /*#__PURE__*/ jsx(Dialog, {
|
|
203
|
+
title: request.title,
|
|
204
|
+
description: request.description,
|
|
205
|
+
className: "work-office-dialog",
|
|
206
|
+
focusKey: request.id,
|
|
207
|
+
restoreFocusTarget: ()=>request.restoreFocusTarget?.() ?? invokerRef.current,
|
|
208
|
+
onClose: ()=>'prompt' === request.kind ? closePrompt(null) : 'confirm' === request.kind ? closeConfirm(false) : closeNotice(),
|
|
209
|
+
footer: 'prompt' === request.kind ? /*#__PURE__*/ jsxs(Fragment, {
|
|
210
|
+
children: [
|
|
211
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
212
|
+
tone: "quiet",
|
|
213
|
+
onClick: ()=>closePrompt(null),
|
|
214
|
+
children: "取消"
|
|
215
|
+
}),
|
|
216
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
217
|
+
tone: "primary",
|
|
218
|
+
disabled: Boolean(promptError),
|
|
219
|
+
onClick: submitPrompt,
|
|
220
|
+
children: request.confirmLabel
|
|
221
|
+
})
|
|
222
|
+
]
|
|
223
|
+
}) : 'confirm' === request.kind ? /*#__PURE__*/ jsxs(Fragment, {
|
|
224
|
+
children: [
|
|
225
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
226
|
+
tone: "quiet",
|
|
227
|
+
onClick: ()=>closeConfirm(false),
|
|
228
|
+
children: request.cancelLabel
|
|
229
|
+
}),
|
|
230
|
+
/*#__PURE__*/ jsx(button_Button, {
|
|
231
|
+
tone: request.confirmTone,
|
|
232
|
+
onClick: ()=>closeConfirm(true),
|
|
233
|
+
children: request.confirmLabel
|
|
234
|
+
})
|
|
235
|
+
]
|
|
236
|
+
}) : /*#__PURE__*/ jsx(button_Button, {
|
|
237
|
+
tone: "primary",
|
|
238
|
+
onClick: closeNotice,
|
|
239
|
+
children: request.confirmLabel
|
|
240
|
+
}),
|
|
241
|
+
children: 'prompt' === request.kind && /*#__PURE__*/ jsxs("label", {
|
|
242
|
+
className: "work-office-dialog-field",
|
|
243
|
+
htmlFor: promptFieldId,
|
|
244
|
+
children: [
|
|
245
|
+
/*#__PURE__*/ jsx("span", {
|
|
246
|
+
className: "work-office-dialog-field-label",
|
|
247
|
+
children: request.fieldLabel
|
|
248
|
+
}),
|
|
249
|
+
request.multiline ? /*#__PURE__*/ jsx(office_text_field_OfficeTextArea, {
|
|
250
|
+
id: promptFieldId,
|
|
251
|
+
"aria-label": request.fieldLabel,
|
|
252
|
+
"aria-invalid": Boolean(visiblePromptError) || void 0,
|
|
253
|
+
value: request.value,
|
|
254
|
+
placeholder: request.placeholder,
|
|
255
|
+
onChange: (event)=>setRequest({
|
|
256
|
+
...request,
|
|
257
|
+
value: event.target.value,
|
|
258
|
+
touched: true
|
|
259
|
+
}),
|
|
260
|
+
onBlur: ()=>setRequest({
|
|
261
|
+
...request,
|
|
262
|
+
touched: true
|
|
263
|
+
}),
|
|
264
|
+
onKeyDown: (event)=>{
|
|
265
|
+
if ('Enter' === event.key && (event.metaKey || event.ctrlKey)) {
|
|
266
|
+
event.preventDefault();
|
|
267
|
+
submitPrompt();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}) : /*#__PURE__*/ jsx(office_text_field_OfficeTextField, {
|
|
271
|
+
id: promptFieldId,
|
|
272
|
+
"aria-label": request.fieldLabel,
|
|
273
|
+
"aria-invalid": Boolean(visiblePromptError) || void 0,
|
|
274
|
+
value: request.value,
|
|
275
|
+
inputMode: request.inputMode,
|
|
276
|
+
placeholder: request.placeholder,
|
|
277
|
+
onChange: (event)=>setRequest({
|
|
278
|
+
...request,
|
|
279
|
+
value: event.target.value,
|
|
280
|
+
touched: true
|
|
281
|
+
}),
|
|
282
|
+
onBlur: ()=>setRequest({
|
|
283
|
+
...request,
|
|
284
|
+
touched: true
|
|
285
|
+
}),
|
|
286
|
+
onKeyDown: (event)=>{
|
|
287
|
+
if ('Enter' === event.key) {
|
|
288
|
+
event.preventDefault();
|
|
289
|
+
submitPrompt();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}),
|
|
293
|
+
visiblePromptError && /*#__PURE__*/ jsx("span", {
|
|
294
|
+
className: "work-office-dialog-field-error",
|
|
295
|
+
role: "alert",
|
|
296
|
+
children: visiblePromptError
|
|
297
|
+
})
|
|
298
|
+
]
|
|
299
|
+
})
|
|
300
|
+
}, request.id) : null;
|
|
301
|
+
return {
|
|
302
|
+
prompt,
|
|
303
|
+
notice,
|
|
304
|
+
confirm,
|
|
305
|
+
dialog
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function promptValidationMessage(request) {
|
|
309
|
+
if (!request.value.trim() && request.requiredMessage) return request.requiredMessage;
|
|
310
|
+
return request.validate?.(request.value) ?? null;
|
|
311
|
+
}
|
|
312
|
+
function OfficeNumberField({ ariaLabel, value, onValueChange, onCommit, onCancel, min, max, step = 1, disabled = false, className = '', placeholder, escapeConsumer = false, validationInvalid = false }) {
|
|
313
|
+
const commitInProgressRef = useRef(false);
|
|
314
|
+
const numericValue = '' === value ? null : Number(value);
|
|
315
|
+
const invalid = validationInvalid || null !== numericValue && (!Number.isFinite(numericValue) || void 0 !== min && numericValue < min || void 0 !== max && numericValue > max);
|
|
316
|
+
const changeBy = (direction)=>{
|
|
317
|
+
const current = Number(value);
|
|
318
|
+
const fallback = min ?? 0;
|
|
319
|
+
const next = clampNumber(Number.isFinite(current) ? current + step * direction : fallback, min, max);
|
|
320
|
+
const formatted = formatSteppedNumber(next, step);
|
|
321
|
+
onValueChange(formatted);
|
|
322
|
+
onCommit?.(formatted);
|
|
323
|
+
};
|
|
324
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
325
|
+
className: `work-office-number-field ${className}`.trim(),
|
|
326
|
+
children: [
|
|
327
|
+
/*#__PURE__*/ jsx("input", {
|
|
328
|
+
type: "text",
|
|
329
|
+
inputMode: "decimal",
|
|
330
|
+
"aria-label": ariaLabel,
|
|
331
|
+
"aria-invalid": invalid || void 0,
|
|
332
|
+
"data-office-escape-consumer": escapeConsumer || void 0,
|
|
333
|
+
value: value,
|
|
334
|
+
disabled: disabled,
|
|
335
|
+
placeholder: placeholder,
|
|
336
|
+
onChange: (event)=>onValueChange(event.target.value),
|
|
337
|
+
onBlur: (event)=>{
|
|
338
|
+
if (commitInProgressRef.current) return;
|
|
339
|
+
onCommit?.(event.currentTarget.value);
|
|
340
|
+
},
|
|
341
|
+
onKeyDown: (event)=>{
|
|
342
|
+
if ('ArrowUp' === event.key) {
|
|
343
|
+
event.preventDefault();
|
|
344
|
+
changeBy(1);
|
|
345
|
+
} else if ('ArrowDown' === event.key) {
|
|
346
|
+
event.preventDefault();
|
|
347
|
+
changeBy(-1);
|
|
348
|
+
} else if ('Enter' === event.key && onCommit && !event.nativeEvent.isComposing) {
|
|
349
|
+
event.preventDefault();
|
|
350
|
+
event.stopPropagation();
|
|
351
|
+
commitInProgressRef.current = true;
|
|
352
|
+
try {
|
|
353
|
+
onCommit(event.currentTarget.value);
|
|
354
|
+
} finally{
|
|
355
|
+
commitInProgressRef.current = false;
|
|
356
|
+
}
|
|
357
|
+
} else if ('Escape' === event.key && escapeConsumer && onCancel) {
|
|
358
|
+
event.preventDefault();
|
|
359
|
+
event.stopPropagation();
|
|
360
|
+
onCancel();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}),
|
|
364
|
+
/*#__PURE__*/ jsxs("span", {
|
|
365
|
+
className: "work-office-number-steppers",
|
|
366
|
+
children: [
|
|
367
|
+
/*#__PURE__*/ jsx("button", {
|
|
368
|
+
type: "button",
|
|
369
|
+
"aria-label": `增加${ariaLabel}`,
|
|
370
|
+
disabled: disabled,
|
|
371
|
+
onMouseDown: (event)=>event.preventDefault(),
|
|
372
|
+
onClick: ()=>changeBy(1),
|
|
373
|
+
children: /*#__PURE__*/ jsx(ChevronUp, {
|
|
374
|
+
size: 10
|
|
375
|
+
})
|
|
376
|
+
}),
|
|
377
|
+
/*#__PURE__*/ jsx("button", {
|
|
378
|
+
type: "button",
|
|
379
|
+
"aria-label": `减少${ariaLabel}`,
|
|
380
|
+
disabled: disabled,
|
|
381
|
+
onMouseDown: (event)=>event.preventDefault(),
|
|
382
|
+
onClick: ()=>changeBy(-1),
|
|
383
|
+
children: /*#__PURE__*/ jsx(ChevronDown, {
|
|
384
|
+
size: 10
|
|
385
|
+
})
|
|
386
|
+
})
|
|
387
|
+
]
|
|
388
|
+
})
|
|
389
|
+
]
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
function CommittedOfficeNumberField({ value, normalizeValue, onValueCommit, formatValue = defaultNumberFormat, ...fieldProps }) {
|
|
393
|
+
const controlledDraft = void 0 === value ? '' : formatValue(value);
|
|
394
|
+
const [draft, setDraft] = useState(controlledDraft);
|
|
395
|
+
const normalizedDraft = safelyNormalizeOfficeNumberDraft(normalizeValue, draft);
|
|
396
|
+
useEffect(()=>setDraft(controlledDraft), [
|
|
397
|
+
controlledDraft
|
|
398
|
+
]);
|
|
399
|
+
const commit = (rawValue)=>{
|
|
400
|
+
const normalized = safelyNormalizeOfficeNumberDraft(normalizeValue, rawValue);
|
|
401
|
+
if (null === normalized || void 0 !== normalized && !Number.isFinite(normalized)) return void setDraft(controlledDraft);
|
|
402
|
+
const normalizedDraft = void 0 === normalized ? '' : formatValue(normalized);
|
|
403
|
+
setDraft(normalizedDraft);
|
|
404
|
+
if (!Object.is(normalized, value)) onValueCommit(normalized);
|
|
405
|
+
};
|
|
406
|
+
return /*#__PURE__*/ jsx(OfficeNumberField, {
|
|
407
|
+
...fieldProps,
|
|
408
|
+
escapeConsumer: draft !== controlledDraft,
|
|
409
|
+
validationInvalid: null === normalizedDraft,
|
|
410
|
+
value: draft,
|
|
411
|
+
onValueChange: setDraft,
|
|
412
|
+
onCommit: commit,
|
|
413
|
+
onCancel: ()=>setDraft(controlledDraft)
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
function clampNumber(value, min, max) {
|
|
417
|
+
return Math.min(max ?? 1 / 0, Math.max(min ?? -1 / 0, value));
|
|
418
|
+
}
|
|
419
|
+
function formatSteppedNumber(value, step) {
|
|
420
|
+
const decimalPlaces = Math.max(0, (String(step).split('.')[1] ?? '').length);
|
|
421
|
+
return 0 === decimalPlaces ? String(Math.round(value)) : value.toFixed(decimalPlaces).replace(/\.?0+$/, '');
|
|
422
|
+
}
|
|
423
|
+
function defaultNumberFormat(value) {
|
|
424
|
+
return String(value);
|
|
425
|
+
}
|
|
426
|
+
function safelyNormalizeOfficeNumberDraft(normalizeValue, draft) {
|
|
427
|
+
try {
|
|
428
|
+
return normalizeValue(draft);
|
|
429
|
+
} catch {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function OfficeCheckbox({ ariaLabel, checked, onCheckedChange, children, disabled = false, className = '' }) {
|
|
434
|
+
return /*#__PURE__*/ jsxs("label", {
|
|
435
|
+
className: `work-office-checkbox ${checked ? 'checked' : ''} ${disabled ? 'disabled' : ''} ${className}`.trim(),
|
|
436
|
+
children: [
|
|
437
|
+
/*#__PURE__*/ jsx("input", {
|
|
438
|
+
type: "checkbox",
|
|
439
|
+
"aria-label": ariaLabel,
|
|
440
|
+
checked: checked,
|
|
441
|
+
disabled: disabled,
|
|
442
|
+
onChange: (event)=>onCheckedChange(event.target.checked)
|
|
443
|
+
}),
|
|
444
|
+
/*#__PURE__*/ jsx("span", {
|
|
445
|
+
className: "work-office-checkbox-box",
|
|
446
|
+
"aria-hidden": "true",
|
|
447
|
+
children: checked && /*#__PURE__*/ jsx(Check, {
|
|
448
|
+
size: 11
|
|
449
|
+
})
|
|
450
|
+
}),
|
|
451
|
+
/*#__PURE__*/ jsx("span", {
|
|
452
|
+
className: "work-office-checkbox-label",
|
|
453
|
+
children: children
|
|
454
|
+
})
|
|
455
|
+
]
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
const officeFontFamilies = [
|
|
459
|
+
{
|
|
460
|
+
id: 'microsoft-yahei',
|
|
461
|
+
name: 'Microsoft YaHei',
|
|
462
|
+
cssValue: '"Microsoft YaHei"',
|
|
463
|
+
cssFamily: '"Microsoft YaHei", "PingFang SC", sans-serif',
|
|
464
|
+
label: '微软雅黑',
|
|
465
|
+
group: '中文字体'
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
id: 'pingfang-sc',
|
|
469
|
+
name: 'PingFang SC',
|
|
470
|
+
cssValue: '"PingFang SC"',
|
|
471
|
+
cssFamily: '"PingFang SC", "Microsoft YaHei", sans-serif',
|
|
472
|
+
label: '苹方',
|
|
473
|
+
group: '中文字体'
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
id: 'simsun',
|
|
477
|
+
name: 'SimSun',
|
|
478
|
+
cssValue: 'SimSun',
|
|
479
|
+
cssFamily: 'SimSun, "Songti SC", serif',
|
|
480
|
+
label: '宋体',
|
|
481
|
+
group: '中文字体'
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
id: 'stsong',
|
|
485
|
+
name: 'STSong',
|
|
486
|
+
cssValue: 'STSong',
|
|
487
|
+
cssFamily: 'STSong, "Songti SC", SimSun, serif',
|
|
488
|
+
label: '华文宋体',
|
|
489
|
+
group: '中文字体'
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
id: 'simhei',
|
|
493
|
+
name: 'SimHei',
|
|
494
|
+
cssValue: 'SimHei',
|
|
495
|
+
cssFamily: 'SimHei, "Heiti SC", sans-serif',
|
|
496
|
+
label: '黑体',
|
|
497
|
+
group: '中文字体'
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
id: 'stheiti',
|
|
501
|
+
name: 'STHeiti',
|
|
502
|
+
cssValue: 'STHeiti',
|
|
503
|
+
cssFamily: 'STHeiti, "Heiti SC", SimHei, sans-serif',
|
|
504
|
+
label: '华文黑体',
|
|
505
|
+
group: '中文字体'
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
id: 'kaiti',
|
|
509
|
+
name: 'KaiTi',
|
|
510
|
+
cssValue: 'KaiTi',
|
|
511
|
+
cssFamily: 'KaiTi, "Kaiti SC", serif',
|
|
512
|
+
label: '楷体',
|
|
513
|
+
group: '中文字体'
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
id: 'fangsong',
|
|
517
|
+
name: 'FangSong',
|
|
518
|
+
cssValue: 'FangSong',
|
|
519
|
+
cssFamily: 'FangSong, STFangsong, serif',
|
|
520
|
+
label: '仿宋',
|
|
521
|
+
group: '中文字体'
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
id: 'hiragino-sans-gb',
|
|
525
|
+
name: 'Hiragino Sans GB',
|
|
526
|
+
cssValue: '"Hiragino Sans GB"',
|
|
527
|
+
cssFamily: '"Hiragino Sans GB", "PingFang SC", sans-serif',
|
|
528
|
+
label: '冬青黑体',
|
|
529
|
+
group: '中文字体'
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
id: 'aptos',
|
|
533
|
+
name: 'Aptos',
|
|
534
|
+
cssValue: 'Aptos',
|
|
535
|
+
cssFamily: 'Aptos, sans-serif',
|
|
536
|
+
label: 'Aptos',
|
|
537
|
+
group: '西文字体'
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
id: 'calibri',
|
|
541
|
+
name: 'Calibri',
|
|
542
|
+
cssValue: 'Calibri',
|
|
543
|
+
cssFamily: 'Calibri',
|
|
544
|
+
label: 'Calibri',
|
|
545
|
+
group: '西文字体'
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
id: 'arial',
|
|
549
|
+
name: 'Arial',
|
|
550
|
+
cssValue: 'Arial',
|
|
551
|
+
cssFamily: 'Arial, sans-serif',
|
|
552
|
+
label: 'Arial',
|
|
553
|
+
group: '西文字体'
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
id: 'helvetica',
|
|
557
|
+
name: 'Helvetica',
|
|
558
|
+
cssValue: 'Helvetica',
|
|
559
|
+
cssFamily: 'Helvetica, Arial, sans-serif',
|
|
560
|
+
label: 'Helvetica',
|
|
561
|
+
group: '西文字体'
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
id: 'times-new-roman',
|
|
565
|
+
name: 'Times New Roman',
|
|
566
|
+
cssValue: '"Times New Roman"',
|
|
567
|
+
cssFamily: '"Times New Roman", Times, serif',
|
|
568
|
+
label: 'Times New Roman',
|
|
569
|
+
group: '西文字体'
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
id: 'georgia',
|
|
573
|
+
name: 'Georgia',
|
|
574
|
+
cssValue: 'Georgia',
|
|
575
|
+
cssFamily: 'Georgia, "Times New Roman", serif',
|
|
576
|
+
label: 'Georgia',
|
|
577
|
+
group: '西文字体'
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
id: 'cambria',
|
|
581
|
+
name: 'Cambria',
|
|
582
|
+
cssValue: 'Cambria',
|
|
583
|
+
cssFamily: 'Cambria, Georgia, serif',
|
|
584
|
+
label: 'Cambria',
|
|
585
|
+
group: '西文字体'
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
id: 'garamond',
|
|
589
|
+
name: 'Garamond',
|
|
590
|
+
cssValue: 'Garamond',
|
|
591
|
+
cssFamily: 'Garamond, Georgia, serif',
|
|
592
|
+
label: 'Garamond',
|
|
593
|
+
group: '西文字体'
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
id: 'verdana',
|
|
597
|
+
name: 'Verdana',
|
|
598
|
+
cssValue: 'Verdana',
|
|
599
|
+
cssFamily: 'Verdana, Arial, sans-serif',
|
|
600
|
+
label: 'Verdana',
|
|
601
|
+
group: '西文字体'
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
id: 'tahoma',
|
|
605
|
+
name: 'Tahoma',
|
|
606
|
+
cssValue: 'Tahoma',
|
|
607
|
+
cssFamily: 'Tahoma, Verdana, sans-serif',
|
|
608
|
+
label: 'Tahoma',
|
|
609
|
+
group: '西文字体'
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
id: 'trebuchet-ms',
|
|
613
|
+
name: 'Trebuchet MS',
|
|
614
|
+
cssValue: '"Trebuchet MS"',
|
|
615
|
+
cssFamily: '"Trebuchet MS", Arial, sans-serif',
|
|
616
|
+
label: 'Trebuchet MS',
|
|
617
|
+
group: '西文字体'
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
id: 'sf-mono',
|
|
621
|
+
name: 'SFMono-Regular',
|
|
622
|
+
cssValue: 'SFMono-Regular',
|
|
623
|
+
cssFamily: 'SFMono-Regular, Menlo, Consolas, monospace',
|
|
624
|
+
label: 'SF Mono',
|
|
625
|
+
group: '等宽字体'
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
id: 'menlo',
|
|
629
|
+
name: 'Menlo',
|
|
630
|
+
cssValue: 'Menlo',
|
|
631
|
+
cssFamily: 'Menlo, SFMono-Regular, Consolas, monospace',
|
|
632
|
+
label: 'Menlo',
|
|
633
|
+
group: '等宽字体'
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
id: 'consolas',
|
|
637
|
+
name: 'Consolas',
|
|
638
|
+
cssValue: 'Consolas',
|
|
639
|
+
cssFamily: 'Consolas, "Courier New", monospace',
|
|
640
|
+
label: 'Consolas',
|
|
641
|
+
group: '等宽字体'
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
id: 'courier-new',
|
|
645
|
+
name: 'Courier New',
|
|
646
|
+
cssValue: '"Courier New"',
|
|
647
|
+
cssFamily: '"Courier New", Courier, monospace',
|
|
648
|
+
label: 'Courier New',
|
|
649
|
+
group: '等宽字体'
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
id: 'monaco',
|
|
653
|
+
name: 'Monaco',
|
|
654
|
+
cssValue: 'Monaco',
|
|
655
|
+
cssFamily: 'Monaco, Menlo, Consolas, monospace',
|
|
656
|
+
label: 'Monaco',
|
|
657
|
+
group: '等宽字体'
|
|
658
|
+
}
|
|
659
|
+
];
|
|
660
|
+
function officeFontFamilyLabel(value) {
|
|
661
|
+
const firstFamily = value.split(',')[0]?.trim() || value.trim();
|
|
662
|
+
return firstFamily.replace(/^(['"])(.*)\1$/, '$2');
|
|
663
|
+
}
|
|
664
|
+
function normalizeOfficeFontFamily(value) {
|
|
665
|
+
return officeFontFamilyLabel(value).toLocaleLowerCase();
|
|
666
|
+
}
|
|
667
|
+
const MAX_LAYOUT_BLOCKS = 10000;
|
|
668
|
+
const MAX_LAYOUT_EXTENT = 1000000;
|
|
669
|
+
const MAX_LAYOUT_PAGE_INDEX = 1000000;
|
|
670
|
+
function layoutOfficeDocumentInJavaScript(request) {
|
|
671
|
+
validateLayoutRequest(request);
|
|
672
|
+
const availableHeight = Math.max(1, request.page.height - request.page.marginTop - request.page.marginBottom);
|
|
673
|
+
const pages = [
|
|
674
|
+
emptyPage(request.startPageIndex, availableHeight)
|
|
675
|
+
];
|
|
676
|
+
let index = 0;
|
|
677
|
+
while(index < request.blocks.length){
|
|
678
|
+
const block = request.blocks[index];
|
|
679
|
+
if (void 0 !== block.flowCount) {
|
|
680
|
+
const end = index + block.flowCount;
|
|
681
|
+
layoutFlow(request.blocks.slice(index, end), request.blocks.slice(end), pages, availableHeight, end < request.blocks.length);
|
|
682
|
+
index = end;
|
|
683
|
+
} else {
|
|
684
|
+
layoutSingleBlock(block, request.blocks.slice(index + 1), pages, availableHeight, index + 1 < request.blocks.length);
|
|
685
|
+
index += 1;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
if (pages.length > 1 && pages.at(-1)?.placements.length === 0) pages.pop();
|
|
689
|
+
return {
|
|
690
|
+
protocol: 15,
|
|
691
|
+
kind: 'layoutResult',
|
|
692
|
+
requestId: request.requestId,
|
|
693
|
+
revision: request.revision,
|
|
694
|
+
documentRevision: request.documentRevision,
|
|
695
|
+
startPageIndex: request.startPageIndex,
|
|
696
|
+
engine: "javascript",
|
|
697
|
+
pages,
|
|
698
|
+
breaks: layoutBreaks(pages, request)
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
function validateLayoutRequest(request) {
|
|
702
|
+
if (15 !== request.protocol) throw kernelError('office.kernel.protocol_unsupported', `Office kernel protocol ${request.protocol} is unsupported.`);
|
|
703
|
+
if ('layout' !== request.kind) throw kernelError('office.kernel.request_kind_invalid', 'The Office kernel only accepts layout requests at this boundary.');
|
|
704
|
+
if (!Number.isSafeInteger(request.requestId) || request.requestId < 0 || !Number.isSafeInteger(request.revision) || request.revision < 0 || !Number.isSafeInteger(request.documentRevision) || request.documentRevision < 0 || !Number.isSafeInteger(request.startPageIndex) || request.startPageIndex < 0) throw kernelError('office.kernel.revision_invalid', 'Request, layout, and document revisions must be non-negative safe integers.');
|
|
705
|
+
if (request.startPageIndex > MAX_LAYOUT_PAGE_INDEX) throw kernelError('office.kernel.page_index_invalid', `startPageIndex may not exceed ${MAX_LAYOUT_PAGE_INDEX}.`);
|
|
706
|
+
if (request.blocks.length > MAX_LAYOUT_BLOCKS) throw kernelError('office.kernel.block_limit_exceeded', `A layout request may contain at most ${MAX_LAYOUT_BLOCKS} blocks.`);
|
|
707
|
+
for (const [name, value] of Object.entries(request.page))validateExtent(`page.${name}`, value);
|
|
708
|
+
if (request.page.width <= request.page.marginLeft + request.page.marginRight) throw kernelError('office.kernel.page_width_invalid', 'Page width must be greater than its horizontal margins.');
|
|
709
|
+
if (request.page.height <= request.page.marginTop + request.page.marginBottom) throw kernelError('office.kernel.page_height_invalid', 'Page height must leave a positive body area.');
|
|
710
|
+
const blockIds = new Set();
|
|
711
|
+
for (const block of request.blocks){
|
|
712
|
+
if (!block.id.trim() || block.id.length > 256) throw kernelError('office.kernel.block_id_invalid', 'Every layout block requires a non-empty ID of at most 256 bytes.');
|
|
713
|
+
if (blockIds.has(block.id)) throw kernelError('office.kernel.block_id_duplicate', `Layout block ID '${block.id}' is duplicated.`);
|
|
714
|
+
blockIds.add(block.id);
|
|
715
|
+
validateExtent('block.height', block.height);
|
|
716
|
+
validateFlowMetadata(block);
|
|
717
|
+
}
|
|
718
|
+
validateFlowSequences(request.blocks);
|
|
719
|
+
}
|
|
720
|
+
function layoutSingleBlock(block, next, pages, availableHeight, hasMoreBlocks) {
|
|
721
|
+
let current = pages.at(-1);
|
|
722
|
+
let currentHasContent = current.placements.length > 0;
|
|
723
|
+
if (block.breakBefore && currentHasContent) {
|
|
724
|
+
current = emptyPage(nextPageIndex(pages), availableHeight);
|
|
725
|
+
pages.push(current);
|
|
726
|
+
currentHasContent = false;
|
|
727
|
+
}
|
|
728
|
+
const remaining = Math.max(0, availableHeight - current.usedHeight);
|
|
729
|
+
const nextHeight = nextBlockPreviewHeight(next);
|
|
730
|
+
const groupedHeight = block.height + (block.keepWithNext ? nextHeight : 0);
|
|
731
|
+
const shouldAdvance = currentHasContent && (block.height > remaining || (block.keepTogether || block.keepWithNext) && groupedHeight <= availableHeight && groupedHeight > remaining);
|
|
732
|
+
if (shouldAdvance) {
|
|
733
|
+
current = emptyPage(nextPageIndex(pages), availableHeight);
|
|
734
|
+
pages.push(current);
|
|
735
|
+
}
|
|
736
|
+
placeFragment(block, current, availableHeight);
|
|
737
|
+
if (block.breakAfter && hasMoreBlocks) pages.push(emptyPage(nextPageIndex(pages), availableHeight));
|
|
738
|
+
}
|
|
739
|
+
function layoutFlow(blocks, next, pages, availableHeight, hasMoreBlocks) {
|
|
740
|
+
const first = blocks[0];
|
|
741
|
+
const last = blocks.at(-1);
|
|
742
|
+
if (first.breakBefore && pages.at(-1)?.placements.length) pages.push(emptyPage(nextPageIndex(pages), availableHeight));
|
|
743
|
+
const totalHeight = fragmentHeight(blocks, 0, blocks.length);
|
|
744
|
+
const nextHeight = last.keepWithNext ? nextBlockPreviewHeight(next) : 0;
|
|
745
|
+
let current = pages.at(-1);
|
|
746
|
+
const repeatHeaderCount = first.repeatHeaderCount ?? 0;
|
|
747
|
+
const repeatHeaderHeight = first.repeatHeaderHeight ?? 0;
|
|
748
|
+
const groupedHeight = totalHeight + nextHeight;
|
|
749
|
+
if (first.keepTogether && current.placements.length && groupedHeight <= availableHeight && groupedHeight > Math.max(0, availableHeight - current.usedHeight)) {
|
|
750
|
+
current = emptyPage(nextPageIndex(pages), availableHeight);
|
|
751
|
+
pages.push(current);
|
|
752
|
+
}
|
|
753
|
+
if (repeatHeaderCount > 0 && repeatHeaderCount < blocks.length) {
|
|
754
|
+
const leadingHeight = fragmentHeight(blocks, 0, repeatHeaderCount + 1);
|
|
755
|
+
const remainingHeight = Math.max(0, availableHeight - current.usedHeight);
|
|
756
|
+
if (current.placements.length > 0 && leadingHeight <= availableHeight && leadingHeight > remainingHeight) {
|
|
757
|
+
current = emptyPage(nextPageIndex(pages), availableHeight);
|
|
758
|
+
pages.push(current);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
const minimum = Math.max(1, first.minimumFragmentsPerPage ?? 1);
|
|
762
|
+
let cursor = 0;
|
|
763
|
+
while(cursor < blocks.length){
|
|
764
|
+
current = pages.at(-1);
|
|
765
|
+
if (cursor >= repeatHeaderCount && cursor > 0 && repeatHeaderHeight > 0 && 0 === current.placements.length && 0 === current.usedHeight) current.usedHeight = repeatHeaderHeight;
|
|
766
|
+
const currentHasContent = current.placements.length > 0;
|
|
767
|
+
const remainingHeight = Math.max(0, availableHeight - current.usedHeight);
|
|
768
|
+
const remainingFragments = blocks.length - cursor;
|
|
769
|
+
const remainingFlowHeight = fragmentHeight(blocks, cursor, blocks.length);
|
|
770
|
+
if (nextHeight > 0 && currentHasContent && remainingFlowHeight <= remainingHeight && remainingFlowHeight + nextHeight > remainingHeight && remainingFlowHeight + nextHeight <= availableHeight) {
|
|
771
|
+
pages.push(emptyPage(nextPageIndex(pages), availableHeight));
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
let fitting = fragmentsFitting(blocks, cursor, blocks.length, remainingHeight);
|
|
775
|
+
if (fitting === remainingFragments) {
|
|
776
|
+
placeFragments(blocks, cursor, blocks.length, current, availableHeight);
|
|
777
|
+
cursor = blocks.length;
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (0 === fitting) {
|
|
781
|
+
if (currentHasContent) {
|
|
782
|
+
pages.push(emptyPage(nextPageIndex(pages), availableHeight));
|
|
783
|
+
continue;
|
|
784
|
+
}
|
|
785
|
+
fitting = 1;
|
|
786
|
+
}
|
|
787
|
+
if (remainingFragments > minimum) fitting = Math.min(fitting, remainingFragments - minimum);
|
|
788
|
+
const minimumHere = Math.min(minimum, remainingFragments);
|
|
789
|
+
if (fitting < minimumHere && currentHasContent) {
|
|
790
|
+
pages.push(emptyPage(nextPageIndex(pages), availableHeight));
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
793
|
+
fitting = Math.max(1, fitting);
|
|
794
|
+
placeFragments(blocks, cursor, cursor + fitting, current, availableHeight);
|
|
795
|
+
cursor += fitting;
|
|
796
|
+
if (cursor < blocks.length) pages.push(emptyPage(nextPageIndex(pages), availableHeight));
|
|
797
|
+
}
|
|
798
|
+
if (last.breakAfter && hasMoreBlocks) pages.push(emptyPage(nextPageIndex(pages), availableHeight));
|
|
799
|
+
}
|
|
800
|
+
function nextBlockPreviewHeight(blocks) {
|
|
801
|
+
const first = blocks[0];
|
|
802
|
+
if (!first || first.breakBefore) return 0;
|
|
803
|
+
const count = Math.min(2, first.flowCount ?? 1);
|
|
804
|
+
return fragmentHeight(blocks, 0, count);
|
|
805
|
+
}
|
|
806
|
+
function fragmentsFitting(blocks, start, end, availableHeight) {
|
|
807
|
+
let used = 0;
|
|
808
|
+
let count = 0;
|
|
809
|
+
for(let index = start; index < end; index += 1){
|
|
810
|
+
const block = blocks[index];
|
|
811
|
+
if (used + block.height > availableHeight) break;
|
|
812
|
+
used += block.height;
|
|
813
|
+
count += 1;
|
|
814
|
+
}
|
|
815
|
+
return count;
|
|
816
|
+
}
|
|
817
|
+
function placeFragments(blocks, start, end, page, availableHeight) {
|
|
818
|
+
for(let index = start; index < end; index += 1)placeFragment(blocks[index], page, availableHeight);
|
|
819
|
+
}
|
|
820
|
+
function fragmentHeight(blocks, start, end) {
|
|
821
|
+
let height = 0;
|
|
822
|
+
for(let index = start; index < end; index += 1)height += blocks[index].height;
|
|
823
|
+
return height;
|
|
824
|
+
}
|
|
825
|
+
function placeFragment(block, page, availableHeight) {
|
|
826
|
+
const y = page.usedHeight;
|
|
827
|
+
page.placements.push({
|
|
828
|
+
blockId: block.id,
|
|
829
|
+
y,
|
|
830
|
+
height: block.height,
|
|
831
|
+
overflow: block.height > availableHeight || y + block.height > availableHeight
|
|
832
|
+
});
|
|
833
|
+
page.usedHeight += block.height;
|
|
834
|
+
}
|
|
835
|
+
function validateFlowMetadata(block) {
|
|
836
|
+
const values = [
|
|
837
|
+
block.flowId,
|
|
838
|
+
block.flowIndex,
|
|
839
|
+
block.flowCount,
|
|
840
|
+
block.minimumFragmentsPerPage
|
|
841
|
+
];
|
|
842
|
+
const repeatValues = [
|
|
843
|
+
block.repeatHeaderCount,
|
|
844
|
+
block.repeatHeaderHeight
|
|
845
|
+
];
|
|
846
|
+
if (values.every((value)=>void 0 === value) && repeatValues.every((value)=>void 0 === value)) return;
|
|
847
|
+
if (values.some((value)=>void 0 === value)) throw kernelError('office.kernel.flow_metadata_incomplete', 'Flow metadata requires flowId, flowIndex, flowCount, and minimumFragmentsPerPage.');
|
|
848
|
+
if ('string' != typeof block.flowId || !block.flowId.trim() || block.flowId.length > 256) throw kernelError('office.kernel.flow_id_invalid', 'Every layout flow requires a non-empty ID of at most 256 bytes.');
|
|
849
|
+
if (!Number.isSafeInteger(block.flowIndex) || !Number.isSafeInteger(block.flowCount) || block.flowCount <= 0 || block.flowIndex < 0 || block.flowIndex >= block.flowCount) throw kernelError('office.kernel.flow_index_invalid', 'Flow indices must be within a non-empty flow.');
|
|
850
|
+
if (!Number.isSafeInteger(block.minimumFragmentsPerPage) || block.minimumFragmentsPerPage <= 0 || block.minimumFragmentsPerPage > block.flowCount) throw kernelError('office.kernel.flow_minimum_invalid', 'minimumFragmentsPerPage must be within the flow fragment count.');
|
|
851
|
+
if (repeatValues.every((value)=>void 0 === value)) return;
|
|
852
|
+
if (repeatValues.some((value)=>void 0 === value)) throw kernelError('office.kernel.repeat_header_metadata_incomplete', 'Repeated table headers require repeatHeaderCount and repeatHeaderHeight.');
|
|
853
|
+
if (!Number.isSafeInteger(block.repeatHeaderCount) || block.repeatHeaderCount <= 0 || block.repeatHeaderCount >= block.flowCount) throw kernelError('office.kernel.repeat_header_count_invalid', 'repeatHeaderCount must identify a non-empty header before the body rows.');
|
|
854
|
+
validateExtent('block.repeatHeaderHeight', block.repeatHeaderHeight);
|
|
855
|
+
if (block.repeatHeaderHeight <= 0) throw kernelError('office.kernel.repeat_header_height_invalid', 'repeatHeaderHeight must be greater than zero.');
|
|
856
|
+
}
|
|
857
|
+
function validateFlowSequences(blocks) {
|
|
858
|
+
const flowIds = new Set();
|
|
859
|
+
let index = 0;
|
|
860
|
+
while(index < blocks.length){
|
|
861
|
+
const block = blocks[index];
|
|
862
|
+
if (void 0 === block.flowId) {
|
|
863
|
+
index += 1;
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (0 !== block.flowIndex) throw kernelError('office.kernel.flow_sequence_invalid', 'A layout flow must begin with fragment index zero.');
|
|
867
|
+
if (flowIds.has(block.flowId)) throw kernelError('office.kernel.flow_id_duplicate', `Layout flow ID '${block.flowId}' is duplicated.`);
|
|
868
|
+
flowIds.add(block.flowId);
|
|
869
|
+
const count = block.flowCount;
|
|
870
|
+
const repeatHeaderCount = block.repeatHeaderCount;
|
|
871
|
+
const repeatHeaderHeight = block.repeatHeaderHeight;
|
|
872
|
+
const flow = blocks.slice(index, index + count);
|
|
873
|
+
if (flow.length !== count) throw kernelError('office.kernel.flow_sequence_invalid', 'A layout flow must contain its declared number of fragments.');
|
|
874
|
+
flow.forEach((fragment, flowIndex)=>{
|
|
875
|
+
if (fragment.flowId !== block.flowId || fragment.flowIndex !== flowIndex || fragment.flowCount !== count || fragment.minimumFragmentsPerPage !== block.minimumFragmentsPerPage || fragment.repeatHeaderCount !== repeatHeaderCount || fragment.repeatHeaderHeight !== repeatHeaderHeight) throw kernelError('office.kernel.flow_sequence_invalid', 'Layout flow fragments must be consecutive and consistently indexed.');
|
|
876
|
+
if (flowIndex > 0 && fragment.breakBefore) throw kernelError('office.kernel.flow_break_invalid', 'Only the first flow fragment may request breakBefore.');
|
|
877
|
+
if (flowIndex + 1 < count && fragment.breakAfter) throw kernelError('office.kernel.flow_break_invalid', 'Only the last flow fragment may request breakAfter.');
|
|
878
|
+
});
|
|
879
|
+
index += count;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
function emptyPage(index, availableHeight) {
|
|
883
|
+
return {
|
|
884
|
+
index,
|
|
885
|
+
usedHeight: 0,
|
|
886
|
+
availableHeight,
|
|
887
|
+
placements: []
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
function nextPageIndex(pages) {
|
|
891
|
+
return (pages.at(-1)?.index ?? -1) + 1;
|
|
892
|
+
}
|
|
893
|
+
function layoutBreaks(pages, request) {
|
|
894
|
+
return pages.slice(1).flatMap((page, localIndex)=>{
|
|
895
|
+
const beforeBlockId = page.placements[0]?.blockId;
|
|
896
|
+
const previous = pages[localIndex];
|
|
897
|
+
if (!beforeBlockId || !previous) return [];
|
|
898
|
+
const remainingBodyHeight = Math.max(0, previous.availableHeight - previous.usedHeight);
|
|
899
|
+
return [
|
|
900
|
+
{
|
|
901
|
+
beforeBlockId,
|
|
902
|
+
pageIndex: page.index,
|
|
903
|
+
remainingBodyHeight,
|
|
904
|
+
spacerHeight: remainingBodyHeight + request.page.marginBottom + request.page.pageGap + request.page.marginTop
|
|
905
|
+
}
|
|
906
|
+
];
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
function validateExtent(name, value) {
|
|
910
|
+
if (!Number.isFinite(value) || value < 0 || value > MAX_LAYOUT_EXTENT) throw kernelError('office.kernel.extent_invalid', `${name} must be a finite non-negative number.`);
|
|
911
|
+
}
|
|
912
|
+
function kernelError(code, message) {
|
|
913
|
+
return Object.assign(new Error(message), {
|
|
914
|
+
code
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
const MAX_PRESENTATION_ELEMENTS = 10000;
|
|
918
|
+
const MAX_PRESENTATION_EXTENT = 1000000;
|
|
919
|
+
const MAX_PRESENTATION_SNAP_THRESHOLD = 10;
|
|
920
|
+
const PRESENTATION_SLIDE_EXTENT = 100;
|
|
921
|
+
const PRESENTATION_SNAP_EPSILON = 0.000001;
|
|
922
|
+
function resolveOfficePresentationGeometryInJavaScript(request) {
|
|
923
|
+
validatePresentationGeometryRequest(request);
|
|
924
|
+
const operation = request.operation;
|
|
925
|
+
const resolved = 'alignToSlide' === operation.type ? {
|
|
926
|
+
elements: request.elements.map((element)=>alignElementToSlide(element, operation.alignment)),
|
|
927
|
+
guides: []
|
|
928
|
+
} : snapPresentationElement(request.elements, operation.movingElementId, operation.mode, operation.thresholdX, operation.thresholdY);
|
|
929
|
+
return {
|
|
930
|
+
protocol: 15,
|
|
931
|
+
kind: 'presentationGeometryResult',
|
|
932
|
+
requestId: request.requestId,
|
|
933
|
+
revision: request.revision,
|
|
934
|
+
documentRevision: request.documentRevision,
|
|
935
|
+
engine: "javascript",
|
|
936
|
+
...resolved
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
function alignElementToSlide(element, alignment) {
|
|
940
|
+
const maximumX = Math.max(0, PRESENTATION_SLIDE_EXTENT - element.width);
|
|
941
|
+
const maximumY = Math.max(0, PRESENTATION_SLIDE_EXTENT - element.height);
|
|
942
|
+
switch(alignment){
|
|
943
|
+
case 'left':
|
|
944
|
+
return {
|
|
945
|
+
...element,
|
|
946
|
+
x: 0
|
|
947
|
+
};
|
|
948
|
+
case 'center':
|
|
949
|
+
return {
|
|
950
|
+
...element,
|
|
951
|
+
x: maximumX / 2
|
|
952
|
+
};
|
|
953
|
+
case 'right':
|
|
954
|
+
return {
|
|
955
|
+
...element,
|
|
956
|
+
x: maximumX
|
|
957
|
+
};
|
|
958
|
+
case 'top':
|
|
959
|
+
return {
|
|
960
|
+
...element,
|
|
961
|
+
y: 0
|
|
962
|
+
};
|
|
963
|
+
case 'middle':
|
|
964
|
+
return {
|
|
965
|
+
...element,
|
|
966
|
+
y: maximumY / 2
|
|
967
|
+
};
|
|
968
|
+
case 'bottom':
|
|
969
|
+
return {
|
|
970
|
+
...element,
|
|
971
|
+
y: maximumY
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
function snapPresentationElement(elements, movingElementId, mode, thresholdX, thresholdY) {
|
|
976
|
+
const moving = elements.find((element)=>element.id === movingElementId);
|
|
977
|
+
if (!moving) throw office_kernel_presentation_fallback_kernelError('office.kernel.moving_element_missing', `Presentation element '${movingElementId}' does not exist.`);
|
|
978
|
+
const xSnap = presentationSnapForAxis(moving, elements, 'x', mode, thresholdX);
|
|
979
|
+
const ySnap = presentationSnapForAxis(moving, elements, 'y', mode, thresholdY);
|
|
980
|
+
const snapped = applyPresentationSnap(moving, mode, xSnap, ySnap);
|
|
981
|
+
const guides = [
|
|
982
|
+
...xSnap && presentationSnapApplied(moving, snapped, mode, 'x', xSnap.delta) ? [
|
|
983
|
+
xSnap.guide
|
|
984
|
+
] : [],
|
|
985
|
+
...ySnap && presentationSnapApplied(moving, snapped, mode, 'y', ySnap.delta) ? [
|
|
986
|
+
ySnap.guide
|
|
987
|
+
] : []
|
|
988
|
+
];
|
|
989
|
+
return {
|
|
990
|
+
elements: elements.map((element)=>element.id === movingElementId ? snapped : element),
|
|
991
|
+
guides
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
function presentationSnapForAxis(moving, elements, axis, mode, threshold) {
|
|
995
|
+
const targets = [
|
|
996
|
+
...[
|
|
997
|
+
0,
|
|
998
|
+
PRESENTATION_SLIDE_EXTENT / 2,
|
|
999
|
+
PRESENTATION_SLIDE_EXTENT
|
|
1000
|
+
].map((position)=>({
|
|
1001
|
+
position,
|
|
1002
|
+
guide: {
|
|
1003
|
+
axis,
|
|
1004
|
+
position,
|
|
1005
|
+
source: 'slide'
|
|
1006
|
+
}
|
|
1007
|
+
})),
|
|
1008
|
+
...elements.flatMap((element)=>element.id === moving.id ? [] : presentationElementAnchors(element, axis).map((position)=>({
|
|
1009
|
+
position,
|
|
1010
|
+
guide: {
|
|
1011
|
+
axis,
|
|
1012
|
+
position,
|
|
1013
|
+
source: 'element',
|
|
1014
|
+
targetId: element.id
|
|
1015
|
+
}
|
|
1016
|
+
})))
|
|
1017
|
+
];
|
|
1018
|
+
let best = null;
|
|
1019
|
+
for (const movingPosition of presentationMovingAnchors(moving, axis, mode))for (const target of targets){
|
|
1020
|
+
const delta = target.position - movingPosition;
|
|
1021
|
+
const distance = Math.abs(delta);
|
|
1022
|
+
if (distance <= threshold && !presentationResizeSnapCollapsesElement(moving, axis, mode, delta) && (!best || distance < best.distance - PRESENTATION_SNAP_EPSILON)) best = {
|
|
1023
|
+
delta,
|
|
1024
|
+
distance,
|
|
1025
|
+
guide: target.guide
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
return best ? {
|
|
1029
|
+
delta: best.delta,
|
|
1030
|
+
guide: best.guide
|
|
1031
|
+
} : null;
|
|
1032
|
+
}
|
|
1033
|
+
function presentationResizeSnapCollapsesElement(element, axis, mode, delta) {
|
|
1034
|
+
if ('resize' !== mode) return false;
|
|
1035
|
+
const size = 'x' === axis ? element.width : element.height;
|
|
1036
|
+
return size + delta <= 0;
|
|
1037
|
+
}
|
|
1038
|
+
function presentationMovingAnchors(element, axis, mode) {
|
|
1039
|
+
const start = 'x' === axis ? element.x : element.y;
|
|
1040
|
+
const size = 'x' === axis ? element.width : element.height;
|
|
1041
|
+
return 'resize' === mode ? [
|
|
1042
|
+
start + size
|
|
1043
|
+
] : [
|
|
1044
|
+
start,
|
|
1045
|
+
start + size / 2,
|
|
1046
|
+
start + size
|
|
1047
|
+
];
|
|
1048
|
+
}
|
|
1049
|
+
function presentationElementAnchors(element, axis) {
|
|
1050
|
+
const start = 'x' === axis ? element.x : element.y;
|
|
1051
|
+
const size = 'x' === axis ? element.width : element.height;
|
|
1052
|
+
return [
|
|
1053
|
+
start,
|
|
1054
|
+
start + size / 2,
|
|
1055
|
+
start + size
|
|
1056
|
+
];
|
|
1057
|
+
}
|
|
1058
|
+
function applyPresentationSnap(element, mode, xSnap, ySnap) {
|
|
1059
|
+
if ('move' === mode) return {
|
|
1060
|
+
...element,
|
|
1061
|
+
x: clampPresentationExtent(element.x + (xSnap?.delta ?? 0), PRESENTATION_SLIDE_EXTENT - element.width),
|
|
1062
|
+
y: clampPresentationExtent(element.y + (ySnap?.delta ?? 0), PRESENTATION_SLIDE_EXTENT - element.height)
|
|
1063
|
+
};
|
|
1064
|
+
return {
|
|
1065
|
+
...element,
|
|
1066
|
+
width: clampPresentationExtent(element.width + (xSnap?.delta ?? 0), PRESENTATION_SLIDE_EXTENT - element.x),
|
|
1067
|
+
height: clampPresentationExtent(element.height + (ySnap?.delta ?? 0), PRESENTATION_SLIDE_EXTENT - element.y)
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
function presentationSnapApplied(before, after, mode, axis, delta) {
|
|
1071
|
+
const applied = 'move' === mode ? 'x' === axis ? after.x - before.x : after.y - before.y : 'x' === axis ? after.width - before.width : after.height - before.height;
|
|
1072
|
+
return Math.abs(applied - delta) <= PRESENTATION_SNAP_EPSILON;
|
|
1073
|
+
}
|
|
1074
|
+
function clampPresentationExtent(value, maximum) {
|
|
1075
|
+
return Math.min(Math.max(value, 0), Math.max(0, maximum));
|
|
1076
|
+
}
|
|
1077
|
+
function validatePresentationGeometryRequest(request) {
|
|
1078
|
+
if (15 !== request.protocol) throw office_kernel_presentation_fallback_kernelError('office.kernel.protocol_unsupported', `Office kernel protocol ${request.protocol} is unsupported.`);
|
|
1079
|
+
if ('presentationGeometry' !== request.kind) throw office_kernel_presentation_fallback_kernelError('office.kernel.request_kind_invalid', 'The presentation geometry kernel received an invalid request kind.');
|
|
1080
|
+
for (const [name, value] of [
|
|
1081
|
+
[
|
|
1082
|
+
'requestId',
|
|
1083
|
+
request.requestId
|
|
1084
|
+
],
|
|
1085
|
+
[
|
|
1086
|
+
'revision',
|
|
1087
|
+
request.revision
|
|
1088
|
+
],
|
|
1089
|
+
[
|
|
1090
|
+
'documentRevision',
|
|
1091
|
+
request.documentRevision
|
|
1092
|
+
]
|
|
1093
|
+
])if (!Number.isSafeInteger(value) || value < 0) throw office_kernel_presentation_fallback_kernelError('office.kernel.revision_invalid', `${name} must be a non-negative safe integer.`);
|
|
1094
|
+
if (request.elements.length > MAX_PRESENTATION_ELEMENTS) throw office_kernel_presentation_fallback_kernelError('office.kernel.element_limit_exceeded', `A presentation geometry request may contain at most ${MAX_PRESENTATION_ELEMENTS} elements.`);
|
|
1095
|
+
if ('snapElement' === request.operation.type) {
|
|
1096
|
+
if (!request.operation.movingElementId.trim()) throw office_kernel_presentation_fallback_kernelError('office.kernel.moving_element_invalid', 'A presentation snap request requires a moving element ID.');
|
|
1097
|
+
for (const [name, value] of [
|
|
1098
|
+
[
|
|
1099
|
+
'thresholdX',
|
|
1100
|
+
request.operation.thresholdX
|
|
1101
|
+
],
|
|
1102
|
+
[
|
|
1103
|
+
'thresholdY',
|
|
1104
|
+
request.operation.thresholdY
|
|
1105
|
+
]
|
|
1106
|
+
])if (!Number.isFinite(value) || value < 0 || value > MAX_PRESENTATION_SNAP_THRESHOLD) throw office_kernel_presentation_fallback_kernelError('office.kernel.snap_threshold_invalid', `${name} must be between 0 and ${MAX_PRESENTATION_SNAP_THRESHOLD}.`);
|
|
1107
|
+
}
|
|
1108
|
+
const ids = new Set();
|
|
1109
|
+
for (const element of request.elements){
|
|
1110
|
+
if (!element.id.trim() || element.id.length > 256) throw office_kernel_presentation_fallback_kernelError('office.kernel.element_id_invalid', 'Every presentation element requires a non-empty ID of at most 256 bytes.');
|
|
1111
|
+
if (ids.has(element.id)) throw office_kernel_presentation_fallback_kernelError('office.kernel.element_id_duplicate', `Presentation element ID '${element.id}' is duplicated.`);
|
|
1112
|
+
ids.add(element.id);
|
|
1113
|
+
for (const [name, value] of [
|
|
1114
|
+
[
|
|
1115
|
+
'x',
|
|
1116
|
+
element.x
|
|
1117
|
+
],
|
|
1118
|
+
[
|
|
1119
|
+
'y',
|
|
1120
|
+
element.y
|
|
1121
|
+
],
|
|
1122
|
+
[
|
|
1123
|
+
'width',
|
|
1124
|
+
element.width
|
|
1125
|
+
],
|
|
1126
|
+
[
|
|
1127
|
+
'height',
|
|
1128
|
+
element.height
|
|
1129
|
+
]
|
|
1130
|
+
])if (!Number.isFinite(value) || value < 0 || value > MAX_PRESENTATION_EXTENT) throw office_kernel_presentation_fallback_kernelError('office.kernel.extent_invalid', `element.${name} must be a finite non-negative number.`);
|
|
1131
|
+
if (element.width <= 0 || element.height <= 0) throw office_kernel_presentation_fallback_kernelError('office.kernel.element_size_invalid', 'Presentation element width and height must be positive.');
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
function office_kernel_presentation_fallback_kernelError(code, message) {
|
|
1135
|
+
return Object.assign(new Error(message), {
|
|
1136
|
+
code
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
const browserScalarFunctionArities = new Map([
|
|
1140
|
+
[
|
|
1141
|
+
'ABS',
|
|
1142
|
+
[
|
|
1143
|
+
1,
|
|
1144
|
+
1
|
|
1145
|
+
]
|
|
1146
|
+
],
|
|
1147
|
+
[
|
|
1148
|
+
'AND',
|
|
1149
|
+
[
|
|
1150
|
+
1,
|
|
1151
|
+
255
|
|
1152
|
+
]
|
|
1153
|
+
],
|
|
1154
|
+
[
|
|
1155
|
+
'AVERAGE',
|
|
1156
|
+
[
|
|
1157
|
+
1,
|
|
1158
|
+
255
|
|
1159
|
+
]
|
|
1160
|
+
],
|
|
1161
|
+
[
|
|
1162
|
+
'COLUMN',
|
|
1163
|
+
[
|
|
1164
|
+
0,
|
|
1165
|
+
0
|
|
1166
|
+
]
|
|
1167
|
+
],
|
|
1168
|
+
[
|
|
1169
|
+
'CONCAT',
|
|
1170
|
+
[
|
|
1171
|
+
1,
|
|
1172
|
+
255
|
|
1173
|
+
]
|
|
1174
|
+
],
|
|
1175
|
+
[
|
|
1176
|
+
'CONCATENATE',
|
|
1177
|
+
[
|
|
1178
|
+
1,
|
|
1179
|
+
255
|
|
1180
|
+
]
|
|
1181
|
+
],
|
|
1182
|
+
[
|
|
1183
|
+
'COUNT',
|
|
1184
|
+
[
|
|
1185
|
+
1,
|
|
1186
|
+
255
|
|
1187
|
+
]
|
|
1188
|
+
],
|
|
1189
|
+
[
|
|
1190
|
+
'COUNTA',
|
|
1191
|
+
[
|
|
1192
|
+
1,
|
|
1193
|
+
255
|
|
1194
|
+
]
|
|
1195
|
+
],
|
|
1196
|
+
[
|
|
1197
|
+
'FALSE',
|
|
1198
|
+
[
|
|
1199
|
+
0,
|
|
1200
|
+
0
|
|
1201
|
+
]
|
|
1202
|
+
],
|
|
1203
|
+
[
|
|
1204
|
+
'IF',
|
|
1205
|
+
[
|
|
1206
|
+
2,
|
|
1207
|
+
3
|
|
1208
|
+
]
|
|
1209
|
+
],
|
|
1210
|
+
[
|
|
1211
|
+
'IFERROR',
|
|
1212
|
+
[
|
|
1213
|
+
2,
|
|
1214
|
+
2
|
|
1215
|
+
]
|
|
1216
|
+
],
|
|
1217
|
+
[
|
|
1218
|
+
'MAX',
|
|
1219
|
+
[
|
|
1220
|
+
1,
|
|
1221
|
+
255
|
|
1222
|
+
]
|
|
1223
|
+
],
|
|
1224
|
+
[
|
|
1225
|
+
'MIN',
|
|
1226
|
+
[
|
|
1227
|
+
1,
|
|
1228
|
+
255
|
|
1229
|
+
]
|
|
1230
|
+
],
|
|
1231
|
+
[
|
|
1232
|
+
'MOD',
|
|
1233
|
+
[
|
|
1234
|
+
2,
|
|
1235
|
+
2
|
|
1236
|
+
]
|
|
1237
|
+
],
|
|
1238
|
+
[
|
|
1239
|
+
'NA',
|
|
1240
|
+
[
|
|
1241
|
+
0,
|
|
1242
|
+
0
|
|
1243
|
+
]
|
|
1244
|
+
],
|
|
1245
|
+
[
|
|
1246
|
+
'NOT',
|
|
1247
|
+
[
|
|
1248
|
+
1,
|
|
1249
|
+
1
|
|
1250
|
+
]
|
|
1251
|
+
],
|
|
1252
|
+
[
|
|
1253
|
+
'OR',
|
|
1254
|
+
[
|
|
1255
|
+
1,
|
|
1256
|
+
255
|
|
1257
|
+
]
|
|
1258
|
+
],
|
|
1259
|
+
[
|
|
1260
|
+
'PI',
|
|
1261
|
+
[
|
|
1262
|
+
0,
|
|
1263
|
+
0
|
|
1264
|
+
]
|
|
1265
|
+
],
|
|
1266
|
+
[
|
|
1267
|
+
'POWER',
|
|
1268
|
+
[
|
|
1269
|
+
2,
|
|
1270
|
+
2
|
|
1271
|
+
]
|
|
1272
|
+
],
|
|
1273
|
+
[
|
|
1274
|
+
'ROUND',
|
|
1275
|
+
[
|
|
1276
|
+
2,
|
|
1277
|
+
2
|
|
1278
|
+
]
|
|
1279
|
+
],
|
|
1280
|
+
[
|
|
1281
|
+
'ROW',
|
|
1282
|
+
[
|
|
1283
|
+
0,
|
|
1284
|
+
0
|
|
1285
|
+
]
|
|
1286
|
+
],
|
|
1287
|
+
[
|
|
1288
|
+
'SQRT',
|
|
1289
|
+
[
|
|
1290
|
+
1,
|
|
1291
|
+
1
|
|
1292
|
+
]
|
|
1293
|
+
],
|
|
1294
|
+
[
|
|
1295
|
+
'SUM',
|
|
1296
|
+
[
|
|
1297
|
+
1,
|
|
1298
|
+
255
|
|
1299
|
+
]
|
|
1300
|
+
],
|
|
1301
|
+
[
|
|
1302
|
+
'TRUE',
|
|
1303
|
+
[
|
|
1304
|
+
0,
|
|
1305
|
+
0
|
|
1306
|
+
]
|
|
1307
|
+
]
|
|
1308
|
+
]);
|
|
1309
|
+
function normalizeSpreadsheetFunctionName(name) {
|
|
1310
|
+
let normalized = name.toUpperCase();
|
|
1311
|
+
while(normalized.startsWith('_XLFN.') || normalized.startsWith('_XLWS.'))normalized = normalized.slice(6);
|
|
1312
|
+
return normalized;
|
|
1313
|
+
}
|
|
1314
|
+
function normalizeFormulaForFortuneParser(formula) {
|
|
1315
|
+
const source = formula.replace(/^=/, '');
|
|
1316
|
+
let output = '';
|
|
1317
|
+
let cursor = 0;
|
|
1318
|
+
let bracketDepth = 0;
|
|
1319
|
+
while(cursor < source.length){
|
|
1320
|
+
const character = source[cursor] ?? '';
|
|
1321
|
+
if ('"' === character || "'" === character) {
|
|
1322
|
+
const quote = character;
|
|
1323
|
+
output += quote;
|
|
1324
|
+
cursor += 1;
|
|
1325
|
+
while(cursor < source.length){
|
|
1326
|
+
const quoted = source[cursor] ?? '';
|
|
1327
|
+
output += quoted;
|
|
1328
|
+
cursor += 1;
|
|
1329
|
+
if (quoted !== quote) continue;
|
|
1330
|
+
if (source[cursor] === quote) {
|
|
1331
|
+
output += quote;
|
|
1332
|
+
cursor += 1;
|
|
1333
|
+
continue;
|
|
1334
|
+
}
|
|
1335
|
+
break;
|
|
1336
|
+
}
|
|
1337
|
+
continue;
|
|
1338
|
+
}
|
|
1339
|
+
if ('[' === character) {
|
|
1340
|
+
bracketDepth += 1;
|
|
1341
|
+
output += character;
|
|
1342
|
+
cursor += 1;
|
|
1343
|
+
continue;
|
|
1344
|
+
}
|
|
1345
|
+
if (']' === character && bracketDepth > 0) {
|
|
1346
|
+
bracketDepth -= 1;
|
|
1347
|
+
output += character;
|
|
1348
|
+
cursor += 1;
|
|
1349
|
+
continue;
|
|
1350
|
+
}
|
|
1351
|
+
if (0 === bracketDepth && isAsciiFormulaNameStart(character)) {
|
|
1352
|
+
const start = cursor;
|
|
1353
|
+
cursor += 1;
|
|
1354
|
+
while(cursor < source.length && isAsciiFormulaNameContinue(source[cursor] ?? ''))cursor += 1;
|
|
1355
|
+
const token = source.slice(start, cursor);
|
|
1356
|
+
const normalized = token.toUpperCase();
|
|
1357
|
+
const normalizedFunction = normalizeSpreadsheetFunctionName(token);
|
|
1358
|
+
const previous = adjacentNonWhitespace(source, start - 1, -1);
|
|
1359
|
+
const next = adjacentNonWhitespace(source, cursor, 1);
|
|
1360
|
+
if ('(' === next && normalizedFunction !== normalized) output += normalizedFunction;
|
|
1361
|
+
else if (('TRUE' === normalized || 'FALSE' === normalized) && '!' !== previous && '!' !== next && '(' !== next) output += `${token}()`;
|
|
1362
|
+
else output += token;
|
|
1363
|
+
continue;
|
|
1364
|
+
}
|
|
1365
|
+
output += character;
|
|
1366
|
+
cursor += 1;
|
|
1367
|
+
}
|
|
1368
|
+
return output;
|
|
1369
|
+
}
|
|
1370
|
+
function adjacentNonWhitespace(value, start, direction) {
|
|
1371
|
+
let cursor = start;
|
|
1372
|
+
while(cursor >= 0 && cursor < value.length){
|
|
1373
|
+
const character = value[cursor];
|
|
1374
|
+
if (character && !/\s/u.test(character)) return character;
|
|
1375
|
+
cursor += direction;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
function isAsciiFormulaNameStart(value) {
|
|
1379
|
+
return /[A-Za-z_]/u.test(value);
|
|
1380
|
+
}
|
|
1381
|
+
function isAsciiFormulaNameContinue(value) {
|
|
1382
|
+
return /[A-Za-z0-9_.]/u.test(value);
|
|
1383
|
+
}
|
|
1384
|
+
const office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS = 1048576;
|
|
1385
|
+
const spreadsheetErrors = new Set([
|
|
1386
|
+
'#BLOCKED!',
|
|
1387
|
+
'#BUSY!',
|
|
1388
|
+
'#CALC!',
|
|
1389
|
+
'#CONNECT!',
|
|
1390
|
+
'#DIV/0!',
|
|
1391
|
+
'#FIELD!',
|
|
1392
|
+
'#GETTING_DATA',
|
|
1393
|
+
'#N/A',
|
|
1394
|
+
'#NAME?',
|
|
1395
|
+
'#NULL!',
|
|
1396
|
+
'#NUM!',
|
|
1397
|
+
'#PYTHON!',
|
|
1398
|
+
'#REF!',
|
|
1399
|
+
'#SPILL!',
|
|
1400
|
+
'#UNKNOWN!',
|
|
1401
|
+
'#VALUE!'
|
|
1402
|
+
]);
|
|
1403
|
+
new TextEncoder();
|
|
1404
|
+
function isOfficeKernelSpreadsheetError(value) {
|
|
1405
|
+
return 'string' == typeof value && spreadsheetErrors.has(value);
|
|
1406
|
+
}
|
|
1407
|
+
const MAX_SPREADSHEET_INPUT_CELLS = 100000;
|
|
1408
|
+
const MAX_SPREADSHEET_FORMULA_CHARACTERS = 8192;
|
|
1409
|
+
const MAX_SPREADSHEET_SHEETS = 1024;
|
|
1410
|
+
const MAX_SPREADSHEET_IDENTIFIER_BYTES = 256;
|
|
1411
|
+
const MAX_UNSIGNED_32_BIT_INTEGER = 4294967295;
|
|
1412
|
+
function validateSpreadsheetCalculationRequest(request) {
|
|
1413
|
+
if (15 !== request.protocol) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.protocol_unsupported', `Office kernel protocol ${request.protocol} is unsupported.`);
|
|
1414
|
+
if ('spreadsheetCalculation' !== request.kind) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.request_kind_invalid', 'The Spreadsheet kernel only accepts calculation requests.');
|
|
1415
|
+
if (!unsigned32BitInteger(request.requestId) || !unsigned32BitInteger(request.revision) || !nonNegativeSafeInteger(request.documentRevision)) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.revision_invalid', 'Request, calculation, and document revisions must be non-negative safe integers.');
|
|
1416
|
+
if (request.sheets.length > MAX_SPREADSHEET_SHEETS) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.sheet_limit_exceeded', `A Spreadsheet calculation request may contain at most ${MAX_SPREADSHEET_SHEETS} sheets.`);
|
|
1417
|
+
const totalCells = request.sheets.reduce((count, sheet)=>count + sheet.cells.length, 0);
|
|
1418
|
+
if (totalCells > MAX_SPREADSHEET_INPUT_CELLS) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.cell_limit_exceeded', `A Spreadsheet calculation request may contain at most ${MAX_SPREADSHEET_INPUT_CELLS} populated cells.`);
|
|
1419
|
+
if (request.targets && request.targets.length > MAX_SPREADSHEET_INPUT_CELLS) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.target_limit_exceeded', `A Spreadsheet calculation request may contain at most ${MAX_SPREADSHEET_INPUT_CELLS} targets.`);
|
|
1420
|
+
const sheetIds = new Set();
|
|
1421
|
+
const sheetNames = new Set();
|
|
1422
|
+
for (const sheet of request.sheets){
|
|
1423
|
+
const normalizedName = sheet.name.toLowerCase();
|
|
1424
|
+
if (!sheet.id.trim() || utf8ByteLength(sheet.id) > MAX_SPREADSHEET_IDENTIFIER_BYTES || !sheet.name.trim() || utf8ByteLength(sheet.name) > MAX_SPREADSHEET_IDENTIFIER_BYTES || sheetIds.has(sheet.id) || sheetNames.has(normalizedName)) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.sheet_invalid', 'Spreadsheet sheet IDs and names must be unique and non-empty.');
|
|
1425
|
+
sheetIds.add(sheet.id);
|
|
1426
|
+
sheetNames.add(normalizedName);
|
|
1427
|
+
const coordinates = new Set();
|
|
1428
|
+
for (const cell of sheet.cells){
|
|
1429
|
+
const key = `${cell.row}:${cell.column}`;
|
|
1430
|
+
if (!boundedSpreadsheetIndex(cell.row, office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !boundedSpreadsheetIndex(cell.column, 16384) || coordinates.has(key)) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.cell_invalid', 'Spreadsheet cells require unique, bounded row and column coordinates.');
|
|
1431
|
+
coordinates.add(key);
|
|
1432
|
+
validateSpreadsheetValue(cell.value);
|
|
1433
|
+
if (void 0 !== cell.formula && (0 === cell.formula.length || Array.from(cell.formula).length > MAX_SPREADSHEET_FORMULA_CHARACTERS)) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.formula_invalid', `Spreadsheet formulas must contain 1-${MAX_SPREADSHEET_FORMULA_CHARACTERS} characters.`);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
for (const target of request.targets ?? [])if (!sheetIds.has(target.sheetId) || !boundedSpreadsheetIndex(target.row, office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !boundedSpreadsheetIndex(target.column, 16384)) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.target_invalid', 'Spreadsheet calculation targets must reference an existing, bounded cell.');
|
|
1437
|
+
}
|
|
1438
|
+
function boundedSpreadsheetIndex(value, exclusiveMaximum) {
|
|
1439
|
+
return Number.isSafeInteger(value) && value >= 0 && value < exclusiveMaximum;
|
|
1440
|
+
}
|
|
1441
|
+
function validateSpreadsheetValue(value) {
|
|
1442
|
+
if ('number' === value.kind && !Number.isFinite(value.value)) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.value_invalid', 'Spreadsheet numeric values must be finite.');
|
|
1443
|
+
if ('text' === value.kind && utf8ByteLength(value.value) > 32767) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.value_invalid', "Spreadsheet text values may contain at most 32767 UTF-8 bytes.");
|
|
1444
|
+
if ('error' === value.kind && !isOfficeKernelSpreadsheetError(value.value)) throw office_kernel_spreadsheet_fallback_validation_kernelError('office.kernel.spreadsheet.value_invalid', `Spreadsheet error value '${value.value}' is not recognized.`);
|
|
1445
|
+
}
|
|
1446
|
+
function nonNegativeSafeInteger(value) {
|
|
1447
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
1448
|
+
}
|
|
1449
|
+
function unsigned32BitInteger(value) {
|
|
1450
|
+
return nonNegativeSafeInteger(value) && value <= MAX_UNSIGNED_32_BIT_INTEGER;
|
|
1451
|
+
}
|
|
1452
|
+
function utf8ByteLength(value) {
|
|
1453
|
+
return new TextEncoder().encode(value).byteLength;
|
|
1454
|
+
}
|
|
1455
|
+
function office_kernel_spreadsheet_fallback_validation_kernelError(code, message) {
|
|
1456
|
+
return Object.assign(new Error(message), {
|
|
1457
|
+
code
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
const textEncoder = new TextEncoder();
|
|
1461
|
+
function spreadsheetValueFromParser(value) {
|
|
1462
|
+
if (Array.isArray(value)) {
|
|
1463
|
+
const first = value[0];
|
|
1464
|
+
return spreadsheetValueFromParser(Array.isArray(first) ? first[0] : first);
|
|
1465
|
+
}
|
|
1466
|
+
if (null == value || '' === value) return {
|
|
1467
|
+
kind: 'blank'
|
|
1468
|
+
};
|
|
1469
|
+
if ('number' == typeof value) return Number.isFinite(value) ? {
|
|
1470
|
+
kind: 'number',
|
|
1471
|
+
value: Object.is(value, -0) ? 0 : value
|
|
1472
|
+
} : {
|
|
1473
|
+
kind: 'error',
|
|
1474
|
+
value: '#NUM!'
|
|
1475
|
+
};
|
|
1476
|
+
if ('boolean' == typeof value) return {
|
|
1477
|
+
kind: 'boolean',
|
|
1478
|
+
value
|
|
1479
|
+
};
|
|
1480
|
+
if (value instanceof Error) return {
|
|
1481
|
+
kind: 'error',
|
|
1482
|
+
value: spreadsheetError(value.message)
|
|
1483
|
+
};
|
|
1484
|
+
if ('string' == typeof value && !value.startsWith('#')) {
|
|
1485
|
+
const error = recognizedSpreadsheetError(value);
|
|
1486
|
+
if (error) return {
|
|
1487
|
+
kind: 'error',
|
|
1488
|
+
value: error
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
const text = String(value);
|
|
1492
|
+
return textEncoder.encode(text).byteLength <= 32767 ? {
|
|
1493
|
+
kind: 'text',
|
|
1494
|
+
value: text
|
|
1495
|
+
} : {
|
|
1496
|
+
kind: 'error',
|
|
1497
|
+
value: '#VALUE!'
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
function spreadsheetValueForParser(value) {
|
|
1501
|
+
switch(value.kind){
|
|
1502
|
+
case 'blank':
|
|
1503
|
+
return null;
|
|
1504
|
+
case 'number':
|
|
1505
|
+
case 'text':
|
|
1506
|
+
case 'boolean':
|
|
1507
|
+
return value.value;
|
|
1508
|
+
case 'error':
|
|
1509
|
+
return new Error(value.value);
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
function spreadsheetError(value) {
|
|
1513
|
+
return recognizedSpreadsheetError(value) ?? '#VALUE!';
|
|
1514
|
+
}
|
|
1515
|
+
function recognizedSpreadsheetError(value) {
|
|
1516
|
+
const normalized = value.startsWith('#') ? value : `#${value}`;
|
|
1517
|
+
const withSuffix = '#DIV/0' === normalized ? '#DIV/0!' : normalized;
|
|
1518
|
+
return isOfficeKernelSpreadsheetError(withSuffix) ? withSuffix : null;
|
|
1519
|
+
}
|
|
1520
|
+
function evaluateParserIfError(parameters) {
|
|
1521
|
+
const [value, fallback = null] = parameters;
|
|
1522
|
+
return isParserErrorValue(value) ? fallback : value;
|
|
1523
|
+
}
|
|
1524
|
+
function isParserErrorValue(value) {
|
|
1525
|
+
if (value instanceof Error) return true;
|
|
1526
|
+
if ('string' != typeof value || value.startsWith('#')) return false;
|
|
1527
|
+
const normalized = `#${value}`;
|
|
1528
|
+
const withSuffix = '#DIV/0' === normalized ? '#DIV/0!' : normalized;
|
|
1529
|
+
return isOfficeKernelSpreadsheetError(withSuffix);
|
|
1530
|
+
}
|
|
1531
|
+
async function calculateSpreadsheetInJavaScript(request) {
|
|
1532
|
+
validateSpreadsheetCalculationRequest(request);
|
|
1533
|
+
const formulaParser = await import("@fortune-sheet/formula-parser");
|
|
1534
|
+
const evaluator = new JavaScriptSpreadsheetEvaluator(request, formulaParser);
|
|
1535
|
+
return evaluator.calculate();
|
|
1536
|
+
}
|
|
1537
|
+
class JavaScriptSpreadsheetEvaluator {
|
|
1538
|
+
request;
|
|
1539
|
+
formulaParser;
|
|
1540
|
+
cells = new Map();
|
|
1541
|
+
sheetsByName = new Map();
|
|
1542
|
+
states = new Map();
|
|
1543
|
+
stack = [];
|
|
1544
|
+
calculationOrder = [];
|
|
1545
|
+
issues = [];
|
|
1546
|
+
constructor(request, formulaParser){
|
|
1547
|
+
this.request = request;
|
|
1548
|
+
this.formulaParser = formulaParser;
|
|
1549
|
+
for (const sheet of request.sheets){
|
|
1550
|
+
this.sheetsByName.set(sheet.name.toLowerCase(), sheet);
|
|
1551
|
+
for (const cell of sheet.cells)this.cells.set(cellKey(sheet.id, cell.row, cell.column), {
|
|
1552
|
+
cell,
|
|
1553
|
+
sheet
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
calculate() {
|
|
1558
|
+
const targets = this.request.targets?.length ? this.request.targets : this.request.sheets.flatMap((sheet)=>sheet.cells.flatMap((cell)=>cell.formula ? [
|
|
1559
|
+
{
|
|
1560
|
+
sheetId: sheet.id,
|
|
1561
|
+
row: cell.row,
|
|
1562
|
+
column: cell.column
|
|
1563
|
+
}
|
|
1564
|
+
] : []).sort((left, right)=>left.row - right.row || left.column - right.column));
|
|
1565
|
+
for (const target of targets)this.evaluateCoordinate(target);
|
|
1566
|
+
const cells = this.calculationOrder.flatMap((coordinate)=>{
|
|
1567
|
+
const state = this.states.get(coordinateKey(coordinate));
|
|
1568
|
+
return state?.successful ? [
|
|
1569
|
+
{
|
|
1570
|
+
...coordinate,
|
|
1571
|
+
value: state.value
|
|
1572
|
+
}
|
|
1573
|
+
] : [];
|
|
1574
|
+
});
|
|
1575
|
+
return {
|
|
1576
|
+
protocol: 15,
|
|
1577
|
+
kind: 'spreadsheetCalculationResult',
|
|
1578
|
+
requestId: this.request.requestId,
|
|
1579
|
+
revision: this.request.revision,
|
|
1580
|
+
documentRevision: this.request.documentRevision,
|
|
1581
|
+
engine: "javascript",
|
|
1582
|
+
cells,
|
|
1583
|
+
calculationOrder: this.calculationOrder.filter((coordinate)=>this.states.get(coordinateKey(coordinate))?.successful),
|
|
1584
|
+
issues: this.issues
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1587
|
+
evaluateCoordinate(coordinate) {
|
|
1588
|
+
const key = coordinateKey(coordinate);
|
|
1589
|
+
const cached = this.states.get(key);
|
|
1590
|
+
if (cached) return cached.value;
|
|
1591
|
+
const indexed = this.cells.get(key);
|
|
1592
|
+
if (!indexed) return {
|
|
1593
|
+
kind: 'blank'
|
|
1594
|
+
};
|
|
1595
|
+
if (!indexed.cell.formula) return indexed.cell.value;
|
|
1596
|
+
const cycleStart = this.stack.indexOf(key);
|
|
1597
|
+
if (cycleStart >= 0) {
|
|
1598
|
+
this.markCycle(cycleStart);
|
|
1599
|
+
return this.states.get(key)?.value ?? indexed.cell.value;
|
|
1600
|
+
}
|
|
1601
|
+
if (this.stack.length >= 64) {
|
|
1602
|
+
this.recordState(key, indexed.cell.value, false, calculationIssue(coordinate, 'office.kernel.spreadsheet.dependency_depth_exceeded', "Spreadsheet formula dependency depth may not exceed 64."));
|
|
1603
|
+
return indexed.cell.value;
|
|
1604
|
+
}
|
|
1605
|
+
this.stack.push(key);
|
|
1606
|
+
let state;
|
|
1607
|
+
try {
|
|
1608
|
+
state = this.evaluateFormula(coordinate, indexed);
|
|
1609
|
+
} finally{
|
|
1610
|
+
this.stack.pop();
|
|
1611
|
+
}
|
|
1612
|
+
const cycleState = this.states.get(key);
|
|
1613
|
+
if (cycleState) return cycleState.value;
|
|
1614
|
+
this.recordState(key, state.value, state.successful, state.issue);
|
|
1615
|
+
return state.value;
|
|
1616
|
+
}
|
|
1617
|
+
evaluateFormula(coordinate, indexed) {
|
|
1618
|
+
const formula = indexed.cell.formula ?? '';
|
|
1619
|
+
const parser = new this.formulaParser.Parser();
|
|
1620
|
+
let unresolvedDependency = false;
|
|
1621
|
+
let unsupportedReference = false;
|
|
1622
|
+
let unsupportedFunction;
|
|
1623
|
+
let materializedRangeCells = 0;
|
|
1624
|
+
parser.setFunction('IFERROR', evaluateParserIfError).setFunction('ROW', (parameters)=>parameters.length ? null : coordinate.row + 1).setFunction('COLUMN', (parameters)=>parameters.length ? null : coordinate.column + 1);
|
|
1625
|
+
parser.on('callFunction', (name, parameters)=>{
|
|
1626
|
+
const normalized = normalizeSpreadsheetFunctionName(name);
|
|
1627
|
+
const arity = browserScalarFunctionArities.get(normalized);
|
|
1628
|
+
if (!arity || parameters.length < arity[0] || parameters.length > arity[1]) unsupportedFunction ??= name.toUpperCase();
|
|
1629
|
+
});
|
|
1630
|
+
parser.on('callCellValue', (cell, _options, done)=>{
|
|
1631
|
+
const dependency = this.resolveCoordinate(indexed.sheet, cell);
|
|
1632
|
+
if (!dependency) {
|
|
1633
|
+
unsupportedReference = true;
|
|
1634
|
+
done(null);
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
const value = this.evaluateCoordinate(dependency);
|
|
1638
|
+
if (this.dependencyRequiresCompatibility(dependency)) unresolvedDependency = true;
|
|
1639
|
+
done(spreadsheetValueForParser(value));
|
|
1640
|
+
});
|
|
1641
|
+
parser.on('callRangeValue', (start, end, _options, done)=>{
|
|
1642
|
+
done(this.rangeValues(indexed.sheet, start, end, ()=>{
|
|
1643
|
+
unresolvedDependency = true;
|
|
1644
|
+
}, ()=>{
|
|
1645
|
+
unsupportedReference = true;
|
|
1646
|
+
}, (cells)=>{
|
|
1647
|
+
if (cells > 100000 - materializedRangeCells) return false;
|
|
1648
|
+
materializedRangeCells += cells;
|
|
1649
|
+
return true;
|
|
1650
|
+
}));
|
|
1651
|
+
});
|
|
1652
|
+
const parsed = parser.parse(normalizeFormulaForFortuneParser(formula), {
|
|
1653
|
+
sheetId: indexed.sheet.id
|
|
1654
|
+
});
|
|
1655
|
+
if (unsupportedFunction) return failedEvaluation(indexed.cell.value, calculationIssue(coordinate, 'office.kernel.spreadsheet.formula_unsupported', `Formula function '${unsupportedFunction}' is not supported.`));
|
|
1656
|
+
if (unsupportedReference) return failedEvaluation(indexed.cell.value, calculationIssue(coordinate, 'office.kernel.spreadsheet.formula_unsupported', 'A formula reference cannot be materialized by the browser fallback.'));
|
|
1657
|
+
if (unresolvedDependency) return failedEvaluation(indexed.cell.value, calculationIssue(coordinate, 'office.kernel.spreadsheet.dependency_unresolved', 'A formula dependency requires compatibility calculation.'));
|
|
1658
|
+
if (parsed.error) {
|
|
1659
|
+
const error = recognizedSpreadsheetError(parsed.error);
|
|
1660
|
+
if (error) return {
|
|
1661
|
+
successful: true,
|
|
1662
|
+
value: {
|
|
1663
|
+
kind: 'error',
|
|
1664
|
+
value: error
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
return failedEvaluation(indexed.cell.value, calculationIssue(coordinate, 'office.kernel.spreadsheet.formula_invalid', 'Formula calculation failed with #VALUE!.'));
|
|
1668
|
+
}
|
|
1669
|
+
return {
|
|
1670
|
+
successful: true,
|
|
1671
|
+
value: spreadsheetValueFromParser(parsed.result)
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
rangeValues(currentSheet, start, end, onUnresolvedDependency, onUnsupportedReference, reserveRangeCells) {
|
|
1675
|
+
const startCoordinate = this.resolveCoordinate(currentSheet, start);
|
|
1676
|
+
const endCoordinate = this.resolveCoordinate(currentSheet, end);
|
|
1677
|
+
if (!startCoordinate || !endCoordinate || startCoordinate.sheetId !== endCoordinate.sheetId) {
|
|
1678
|
+
onUnsupportedReference();
|
|
1679
|
+
return [];
|
|
1680
|
+
}
|
|
1681
|
+
const rowStart = Math.min(startCoordinate.row, endCoordinate.row);
|
|
1682
|
+
const rowEnd = Math.max(startCoordinate.row, endCoordinate.row);
|
|
1683
|
+
const columnStart = Math.min(startCoordinate.column, endCoordinate.column);
|
|
1684
|
+
const columnEnd = Math.max(startCoordinate.column, endCoordinate.column);
|
|
1685
|
+
const cells = (rowEnd - rowStart + 1) * (columnEnd - columnStart + 1);
|
|
1686
|
+
if (cells > 100000 || !reserveRangeCells(cells)) {
|
|
1687
|
+
onUnsupportedReference();
|
|
1688
|
+
return [];
|
|
1689
|
+
}
|
|
1690
|
+
const values = [];
|
|
1691
|
+
for(let row = rowStart; row <= rowEnd; row += 1){
|
|
1692
|
+
const rowValues = [];
|
|
1693
|
+
for(let column = columnStart; column <= columnEnd; column += 1){
|
|
1694
|
+
const dependency = {
|
|
1695
|
+
sheetId: startCoordinate.sheetId,
|
|
1696
|
+
row,
|
|
1697
|
+
column
|
|
1698
|
+
};
|
|
1699
|
+
const value = this.evaluateCoordinate(dependency);
|
|
1700
|
+
if (this.dependencyRequiresCompatibility(dependency)) {
|
|
1701
|
+
onUnresolvedDependency();
|
|
1702
|
+
return [];
|
|
1703
|
+
}
|
|
1704
|
+
rowValues.push(spreadsheetValueForParser(value));
|
|
1705
|
+
}
|
|
1706
|
+
values.push(rowValues);
|
|
1707
|
+
}
|
|
1708
|
+
return values;
|
|
1709
|
+
}
|
|
1710
|
+
dependencyRequiresCompatibility(coordinate) {
|
|
1711
|
+
const state = this.states.get(coordinateKey(coordinate));
|
|
1712
|
+
return state?.successful === false;
|
|
1713
|
+
}
|
|
1714
|
+
resolveCoordinate(currentSheet, coordinate) {
|
|
1715
|
+
const sheet = coordinate.sheetName ? this.sheetsByName.get(coordinate.sheetName.toLowerCase()) : currentSheet;
|
|
1716
|
+
if (!sheet || !boundedSpreadsheetIndex(coordinate.row.index, office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS) || !boundedSpreadsheetIndex(coordinate.column.index, 16384)) return null;
|
|
1717
|
+
return {
|
|
1718
|
+
sheetId: sheet.id,
|
|
1719
|
+
row: coordinate.row.index,
|
|
1720
|
+
column: coordinate.column.index
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
recordState(key, value, successful, issue) {
|
|
1724
|
+
if (this.states.has(key)) return;
|
|
1725
|
+
this.states.set(key, {
|
|
1726
|
+
value,
|
|
1727
|
+
successful,
|
|
1728
|
+
issue
|
|
1729
|
+
});
|
|
1730
|
+
const indexed = this.cells.get(key);
|
|
1731
|
+
if (indexed?.cell.formula) this.calculationOrder.push({
|
|
1732
|
+
sheetId: indexed.sheet.id,
|
|
1733
|
+
row: indexed.cell.row,
|
|
1734
|
+
column: indexed.cell.column
|
|
1735
|
+
});
|
|
1736
|
+
if (issue) this.issues.push(issue);
|
|
1737
|
+
}
|
|
1738
|
+
markCycle(start) {
|
|
1739
|
+
for (const key of this.stack.slice(start)){
|
|
1740
|
+
const indexed = this.cells.get(key);
|
|
1741
|
+
if (indexed) this.recordState(key, indexed.cell.value, false, calculationIssue({
|
|
1742
|
+
sheetId: indexed.sheet.id,
|
|
1743
|
+
row: indexed.cell.row,
|
|
1744
|
+
column: indexed.cell.column
|
|
1745
|
+
}, 'office.kernel.spreadsheet.circular_reference', 'Formula dependency cycle is not supported by this calculation pass.'));
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
function failedEvaluation(value, issue) {
|
|
1750
|
+
return {
|
|
1751
|
+
successful: false,
|
|
1752
|
+
value,
|
|
1753
|
+
issue
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1756
|
+
function calculationIssue(cell, code, message) {
|
|
1757
|
+
return {
|
|
1758
|
+
cell,
|
|
1759
|
+
code,
|
|
1760
|
+
message
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
function coordinateKey(coordinate) {
|
|
1764
|
+
return cellKey(coordinate.sheetId, coordinate.row, coordinate.column);
|
|
1765
|
+
}
|
|
1766
|
+
function cellKey(sheetId, row, column) {
|
|
1767
|
+
return `${sheetId}\u0000${row}\u0000${column}`;
|
|
1768
|
+
}
|
|
1769
|
+
async function calculateSpreadsheetSessionInJavaScript(request, sheets) {
|
|
1770
|
+
const calculationRequest = {
|
|
1771
|
+
protocol: request.protocol,
|
|
1772
|
+
kind: 'spreadsheetCalculation',
|
|
1773
|
+
requestId: request.requestId,
|
|
1774
|
+
revision: request.revision,
|
|
1775
|
+
documentRevision: request.documentRevision,
|
|
1776
|
+
sheets,
|
|
1777
|
+
targets: 'targets' === request.calculation.kind ? request.calculation.targets : void 0
|
|
1778
|
+
};
|
|
1779
|
+
const result = await calculateSpreadsheetInJavaScript(calculationRequest);
|
|
1780
|
+
const formulaKeys = new Set(sheets.flatMap((sheet)=>sheet.cells.flatMap((cell)=>cell.formula ? [
|
|
1781
|
+
`${sheet.id}\u0000${cell.row}\u0000${cell.column}`
|
|
1782
|
+
] : [])));
|
|
1783
|
+
const dirtyFormulaCellCount = 'targets' === request.calculation.kind ? new Set(request.calculation.targets.flatMap((target)=>{
|
|
1784
|
+
const key = `${target.sheetId}\u0000${target.row}\u0000${target.column}`;
|
|
1785
|
+
return formulaKeys.has(key) ? [
|
|
1786
|
+
key
|
|
1787
|
+
] : [];
|
|
1788
|
+
})).size : formulaKeys.size;
|
|
1789
|
+
return {
|
|
1790
|
+
...result,
|
|
1791
|
+
kind: 'spreadsheetSessionCalculationResult',
|
|
1792
|
+
stats: {
|
|
1793
|
+
updateKind: request.update.kind,
|
|
1794
|
+
calculationScope: request.calculation.kind,
|
|
1795
|
+
formulaCellCount: formulaKeys.size,
|
|
1796
|
+
dirtyFormulaCellCount,
|
|
1797
|
+
evaluatedFormulaCellCount: result.calculationOrder.length,
|
|
1798
|
+
reusedFormulaCellCount: 0,
|
|
1799
|
+
dependencyEdgeCount: 0
|
|
1800
|
+
}
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
function layoutOfficeTextInJavaScript(request) {
|
|
1804
|
+
return {
|
|
1805
|
+
protocol: 15,
|
|
1806
|
+
kind: 'textLayoutResult',
|
|
1807
|
+
requestId: request.requestId,
|
|
1808
|
+
revision: request.revision,
|
|
1809
|
+
documentRevision: request.documentRevision,
|
|
1810
|
+
engine: "javascript",
|
|
1811
|
+
layouts: [],
|
|
1812
|
+
unsupportedParagraphIds: request.paragraphs.map((paragraph)=>paragraph.id)
|
|
1813
|
+
};
|
|
1814
|
+
}
|
|
1815
|
+
const OFFICE_KERNEL_WORKER_TIMEOUT_MS = 10000;
|
|
1816
|
+
function createOfficeKernelClient(wasmUrl, fonts = []) {
|
|
1817
|
+
return new BrowserOfficeKernelClient(wasmUrl, fonts);
|
|
1818
|
+
}
|
|
1819
|
+
class BrowserOfficeKernelClient {
|
|
1820
|
+
worker = null;
|
|
1821
|
+
nextRequestId = 1;
|
|
1822
|
+
pendingLayouts = new Map();
|
|
1823
|
+
pendingPresentationGeometry = new Map();
|
|
1824
|
+
pendingTextLayouts = new Map();
|
|
1825
|
+
pendingSpreadsheetCalculations = new Map();
|
|
1826
|
+
pendingSpreadsheetSessionCalculations = new Map();
|
|
1827
|
+
disposed = false;
|
|
1828
|
+
constructor(wasmUrl, fonts = []){
|
|
1829
|
+
if ("u" < typeof Worker) return;
|
|
1830
|
+
try {
|
|
1831
|
+
this.worker = new Worker(new URL('./office-kernel.worker.js', import.meta.url), {
|
|
1832
|
+
name: 'a3s-office-kernel'
|
|
1833
|
+
});
|
|
1834
|
+
this.worker.addEventListener('message', this.handleMessage);
|
|
1835
|
+
this.worker.addEventListener('error', this.handleWorkerFailure);
|
|
1836
|
+
this.worker.postMessage({
|
|
1837
|
+
kind: 'initialize',
|
|
1838
|
+
wasmUrl,
|
|
1839
|
+
fonts
|
|
1840
|
+
});
|
|
1841
|
+
} catch {
|
|
1842
|
+
this.worker = null;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
layout(input, signal) {
|
|
1846
|
+
if (this.disposed) return Promise.reject(disposedError());
|
|
1847
|
+
const request = {
|
|
1848
|
+
protocol: 15,
|
|
1849
|
+
kind: 'layout',
|
|
1850
|
+
requestId: this.nextRequestId++,
|
|
1851
|
+
revision: input.revision,
|
|
1852
|
+
documentRevision: input.documentRevision,
|
|
1853
|
+
startPageIndex: input.startPageIndex ?? 0,
|
|
1854
|
+
page: input.page,
|
|
1855
|
+
blocks: input.blocks
|
|
1856
|
+
};
|
|
1857
|
+
if (signal?.aborted) return Promise.reject(abortError());
|
|
1858
|
+
if (!this.worker) return office_kernel_client_fallbackRequest(request, signal, layoutOfficeDocumentInJavaScript);
|
|
1859
|
+
return new Promise((resolve, reject)=>{
|
|
1860
|
+
const pending = {
|
|
1861
|
+
request,
|
|
1862
|
+
resolve,
|
|
1863
|
+
reject
|
|
1864
|
+
};
|
|
1865
|
+
this.attachPendingRequest(this.pendingLayouts, pending, signal);
|
|
1866
|
+
this.worker?.postMessage({
|
|
1867
|
+
kind: 'layout',
|
|
1868
|
+
request
|
|
1869
|
+
});
|
|
1870
|
+
});
|
|
1871
|
+
}
|
|
1872
|
+
presentationGeometry(input, signal) {
|
|
1873
|
+
if (this.disposed) return Promise.reject(disposedError());
|
|
1874
|
+
const request = {
|
|
1875
|
+
protocol: 15,
|
|
1876
|
+
kind: 'presentationGeometry',
|
|
1877
|
+
requestId: this.nextRequestId++,
|
|
1878
|
+
revision: input.revision,
|
|
1879
|
+
documentRevision: input.documentRevision,
|
|
1880
|
+
operation: input.operation,
|
|
1881
|
+
elements: input.elements
|
|
1882
|
+
};
|
|
1883
|
+
if (signal?.aborted) return Promise.reject(abortError());
|
|
1884
|
+
if (!this.worker) return office_kernel_client_fallbackRequest(request, signal, resolveOfficePresentationGeometryInJavaScript);
|
|
1885
|
+
return new Promise((resolve, reject)=>{
|
|
1886
|
+
const pending = {
|
|
1887
|
+
request,
|
|
1888
|
+
resolve,
|
|
1889
|
+
reject
|
|
1890
|
+
};
|
|
1891
|
+
this.attachPendingRequest(this.pendingPresentationGeometry, pending, signal);
|
|
1892
|
+
this.worker?.postMessage({
|
|
1893
|
+
kind: 'presentationGeometry',
|
|
1894
|
+
request
|
|
1895
|
+
});
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
textLayout(input, signal) {
|
|
1899
|
+
if (this.disposed) return Promise.reject(disposedError());
|
|
1900
|
+
const request = {
|
|
1901
|
+
protocol: 15,
|
|
1902
|
+
kind: 'textLayout',
|
|
1903
|
+
requestId: this.nextRequestId++,
|
|
1904
|
+
revision: input.revision,
|
|
1905
|
+
documentRevision: input.documentRevision,
|
|
1906
|
+
paragraphs: input.paragraphs
|
|
1907
|
+
};
|
|
1908
|
+
if (signal?.aborted) return Promise.reject(abortError());
|
|
1909
|
+
if (!this.worker) return office_kernel_client_fallbackRequest(request, signal, layoutOfficeTextInJavaScript);
|
|
1910
|
+
return new Promise((resolve, reject)=>{
|
|
1911
|
+
const pending = {
|
|
1912
|
+
request,
|
|
1913
|
+
resolve,
|
|
1914
|
+
reject
|
|
1915
|
+
};
|
|
1916
|
+
this.attachPendingRequest(this.pendingTextLayouts, pending, signal);
|
|
1917
|
+
this.worker?.postMessage({
|
|
1918
|
+
kind: 'textLayout',
|
|
1919
|
+
request
|
|
1920
|
+
});
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1923
|
+
spreadsheetCalculation(input, signal) {
|
|
1924
|
+
if (this.disposed) return Promise.reject(disposedError());
|
|
1925
|
+
const request = {
|
|
1926
|
+
protocol: 15,
|
|
1927
|
+
kind: 'spreadsheetCalculation',
|
|
1928
|
+
requestId: this.nextRequestId++,
|
|
1929
|
+
revision: input.revision,
|
|
1930
|
+
documentRevision: input.documentRevision,
|
|
1931
|
+
sheets: input.sheets,
|
|
1932
|
+
targets: input.targets
|
|
1933
|
+
};
|
|
1934
|
+
if (signal?.aborted) return Promise.reject(abortError());
|
|
1935
|
+
if (!this.worker) return office_kernel_client_fallbackRequest(request, signal, calculateSpreadsheetInJavaScript);
|
|
1936
|
+
return new Promise((resolve, reject)=>{
|
|
1937
|
+
const pending = {
|
|
1938
|
+
request,
|
|
1939
|
+
resolve,
|
|
1940
|
+
reject
|
|
1941
|
+
};
|
|
1942
|
+
this.attachPendingRequest(this.pendingSpreadsheetCalculations, pending, signal);
|
|
1943
|
+
this.worker?.postMessage({
|
|
1944
|
+
kind: 'spreadsheetCalculation',
|
|
1945
|
+
request
|
|
1946
|
+
});
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1949
|
+
spreadsheetSessionCalculation(input, signal) {
|
|
1950
|
+
if (this.disposed) return Promise.reject(disposedError());
|
|
1951
|
+
const request = {
|
|
1952
|
+
protocol: 15,
|
|
1953
|
+
kind: 'spreadsheetSessionCalculation',
|
|
1954
|
+
requestId: this.nextRequestId++,
|
|
1955
|
+
revision: input.revision,
|
|
1956
|
+
documentRevision: input.documentRevision,
|
|
1957
|
+
update: input.update,
|
|
1958
|
+
calculation: input.calculation
|
|
1959
|
+
};
|
|
1960
|
+
if (signal?.aborted) return Promise.reject(abortError());
|
|
1961
|
+
if (!this.worker) return fallbackSpreadsheetSessionCalculation(request, input.fallbackSheets, signal);
|
|
1962
|
+
return new Promise((resolve, reject)=>{
|
|
1963
|
+
const pending = {
|
|
1964
|
+
request,
|
|
1965
|
+
fallbackSheets: input.fallbackSheets,
|
|
1966
|
+
resolve,
|
|
1967
|
+
reject
|
|
1968
|
+
};
|
|
1969
|
+
this.attachPendingRequest(this.pendingSpreadsheetSessionCalculations, pending, signal);
|
|
1970
|
+
this.worker?.postMessage({
|
|
1971
|
+
kind: 'spreadsheetSessionCalculation',
|
|
1972
|
+
request
|
|
1973
|
+
});
|
|
1974
|
+
});
|
|
1975
|
+
}
|
|
1976
|
+
dispose() {
|
|
1977
|
+
if (this.disposed) return;
|
|
1978
|
+
this.disposed = true;
|
|
1979
|
+
this.worker?.removeEventListener('message', this.handleMessage);
|
|
1980
|
+
this.worker?.removeEventListener('error', this.handleWorkerFailure);
|
|
1981
|
+
this.worker?.terminate();
|
|
1982
|
+
this.worker = null;
|
|
1983
|
+
this.rejectPendingRequests(this.pendingLayouts, disposedError());
|
|
1984
|
+
this.rejectPendingRequests(this.pendingPresentationGeometry, disposedError());
|
|
1985
|
+
this.rejectPendingRequests(this.pendingTextLayouts, disposedError());
|
|
1986
|
+
this.rejectPendingRequests(this.pendingSpreadsheetCalculations, disposedError());
|
|
1987
|
+
this.rejectPendingRequests(this.pendingSpreadsheetSessionCalculations, disposedError());
|
|
1988
|
+
}
|
|
1989
|
+
attachPendingRequest(pendingRequests, pending, signal) {
|
|
1990
|
+
const requestId = pending.request.requestId;
|
|
1991
|
+
if (signal) {
|
|
1992
|
+
pending.signal = signal;
|
|
1993
|
+
const onAbort = ()=>{
|
|
1994
|
+
pendingRequests.delete(requestId);
|
|
1995
|
+
releasePendingRequest(pending);
|
|
1996
|
+
this.worker?.postMessage({
|
|
1997
|
+
kind: 'cancel',
|
|
1998
|
+
requestId
|
|
1999
|
+
});
|
|
2000
|
+
pending.reject(abortError());
|
|
2001
|
+
};
|
|
2002
|
+
signal.addEventListener('abort', onAbort, {
|
|
2003
|
+
once: true
|
|
2004
|
+
});
|
|
2005
|
+
pending.removeAbortListener = ()=>signal.removeEventListener('abort', onAbort);
|
|
2006
|
+
}
|
|
2007
|
+
pending.timeout = setTimeout(this.handleWorkerFailure, OFFICE_KERNEL_WORKER_TIMEOUT_MS);
|
|
2008
|
+
pendingRequests.set(requestId, pending);
|
|
2009
|
+
}
|
|
2010
|
+
rejectPendingRequests(pendingRequests, error) {
|
|
2011
|
+
for (const pending of pendingRequests.values()){
|
|
2012
|
+
releasePendingRequest(pending);
|
|
2013
|
+
pending.reject(error);
|
|
2014
|
+
}
|
|
2015
|
+
pendingRequests.clear();
|
|
2016
|
+
}
|
|
2017
|
+
handleMessage = (event)=>{
|
|
2018
|
+
if ('response' !== event.data.kind) return;
|
|
2019
|
+
const response = event.data.response;
|
|
2020
|
+
const layout = this.pendingLayouts.get(response.requestId);
|
|
2021
|
+
const geometry = this.pendingPresentationGeometry.get(response.requestId);
|
|
2022
|
+
const textLayout = this.pendingTextLayouts.get(response.requestId);
|
|
2023
|
+
const spreadsheetCalculation = this.pendingSpreadsheetCalculations.get(response.requestId);
|
|
2024
|
+
const spreadsheetSessionCalculation = this.pendingSpreadsheetSessionCalculations.get(response.requestId);
|
|
2025
|
+
const pending = layout ?? geometry ?? textLayout ?? spreadsheetCalculation ?? spreadsheetSessionCalculation;
|
|
2026
|
+
if (!pending) return;
|
|
2027
|
+
this.pendingLayouts.delete(response.requestId);
|
|
2028
|
+
this.pendingPresentationGeometry.delete(response.requestId);
|
|
2029
|
+
this.pendingTextLayouts.delete(response.requestId);
|
|
2030
|
+
this.pendingSpreadsheetCalculations.delete(response.requestId);
|
|
2031
|
+
this.pendingSpreadsheetSessionCalculations.delete(response.requestId);
|
|
2032
|
+
releasePendingRequest(pending);
|
|
2033
|
+
if ('error' === response.kind) return void pending.reject(Object.assign(new Error(response.error.message), {
|
|
2034
|
+
code: response.error.code
|
|
2035
|
+
}));
|
|
2036
|
+
if ('layoutResult' === response.kind && layout) return void layout.resolve(response);
|
|
2037
|
+
if ('presentationGeometryResult' === response.kind && geometry) return void geometry.resolve(response);
|
|
2038
|
+
if ('textLayoutResult' === response.kind && textLayout) return void textLayout.resolve(response);
|
|
2039
|
+
if ('spreadsheetCalculationResult' === response.kind && spreadsheetCalculation) return void spreadsheetCalculation.resolve(response);
|
|
2040
|
+
if ('spreadsheetSessionCalculationResult' === response.kind && spreadsheetSessionCalculation) return void spreadsheetSessionCalculation.resolve(response);
|
|
2041
|
+
pending.reject(new Error('Office kernel response kind did not match.'));
|
|
2042
|
+
};
|
|
2043
|
+
handleWorkerFailure = ()=>{
|
|
2044
|
+
const layouts = [
|
|
2045
|
+
...this.pendingLayouts.values()
|
|
2046
|
+
];
|
|
2047
|
+
const geometryRequests = [
|
|
2048
|
+
...this.pendingPresentationGeometry.values()
|
|
2049
|
+
];
|
|
2050
|
+
const textLayoutRequests = [
|
|
2051
|
+
...this.pendingTextLayouts.values()
|
|
2052
|
+
];
|
|
2053
|
+
const spreadsheetCalculations = [
|
|
2054
|
+
...this.pendingSpreadsheetCalculations.values()
|
|
2055
|
+
];
|
|
2056
|
+
const spreadsheetSessionCalculations = [
|
|
2057
|
+
...this.pendingSpreadsheetSessionCalculations.values()
|
|
2058
|
+
];
|
|
2059
|
+
this.pendingLayouts.clear();
|
|
2060
|
+
this.pendingPresentationGeometry.clear();
|
|
2061
|
+
this.pendingTextLayouts.clear();
|
|
2062
|
+
this.pendingSpreadsheetCalculations.clear();
|
|
2063
|
+
this.pendingSpreadsheetSessionCalculations.clear();
|
|
2064
|
+
this.worker?.terminate();
|
|
2065
|
+
this.worker = null;
|
|
2066
|
+
for (const pending of layouts){
|
|
2067
|
+
releasePendingRequest(pending);
|
|
2068
|
+
office_kernel_client_fallbackRequest(pending.request, pending.signal, layoutOfficeDocumentInJavaScript).then(pending.resolve, pending.reject);
|
|
2069
|
+
}
|
|
2070
|
+
for (const pending of geometryRequests){
|
|
2071
|
+
releasePendingRequest(pending);
|
|
2072
|
+
office_kernel_client_fallbackRequest(pending.request, pending.signal, resolveOfficePresentationGeometryInJavaScript).then(pending.resolve, pending.reject);
|
|
2073
|
+
}
|
|
2074
|
+
for (const pending of textLayoutRequests){
|
|
2075
|
+
releasePendingRequest(pending);
|
|
2076
|
+
office_kernel_client_fallbackRequest(pending.request, pending.signal, layoutOfficeTextInJavaScript).then(pending.resolve, pending.reject);
|
|
2077
|
+
}
|
|
2078
|
+
for (const pending of spreadsheetCalculations){
|
|
2079
|
+
releasePendingRequest(pending);
|
|
2080
|
+
office_kernel_client_fallbackRequest(pending.request, pending.signal, calculateSpreadsheetInJavaScript).then(pending.resolve, pending.reject);
|
|
2081
|
+
}
|
|
2082
|
+
for (const pending of spreadsheetSessionCalculations){
|
|
2083
|
+
releasePendingRequest(pending);
|
|
2084
|
+
fallbackSpreadsheetSessionCalculation(pending.request, pending.fallbackSheets, pending.signal).then(pending.resolve, pending.reject);
|
|
2085
|
+
}
|
|
2086
|
+
};
|
|
2087
|
+
}
|
|
2088
|
+
async function fallbackSpreadsheetSessionCalculation(request, sheets, signal) {
|
|
2089
|
+
return office_kernel_client_fallbackRequest({
|
|
2090
|
+
request,
|
|
2091
|
+
sheets
|
|
2092
|
+
}, signal, ({ request: fallbackRequest, sheets: fallbackSheets })=>calculateSpreadsheetSessionInJavaScript(fallbackRequest, fallbackSheets));
|
|
2093
|
+
}
|
|
2094
|
+
async function office_kernel_client_fallbackRequest(request, signal, execute) {
|
|
2095
|
+
if (signal?.aborted) throw abortError();
|
|
2096
|
+
const result = await execute(request);
|
|
2097
|
+
if (signal?.aborted) throw abortError();
|
|
2098
|
+
return result;
|
|
2099
|
+
}
|
|
2100
|
+
function releasePendingRequest(pending) {
|
|
2101
|
+
pending.removeAbortListener?.();
|
|
2102
|
+
if (void 0 !== pending.timeout) clearTimeout(pending.timeout);
|
|
2103
|
+
}
|
|
2104
|
+
function abortError() {
|
|
2105
|
+
return new DOMException('Office kernel request was cancelled.', 'AbortError');
|
|
2106
|
+
}
|
|
2107
|
+
function disposedError() {
|
|
2108
|
+
return new Error('Office kernel client is disposed.');
|
|
2109
|
+
}
|
|
2110
|
+
export { CollectionState, CommittedOfficeNumberField, OfficeCheckbox, OfficeNumberField, createOfficeKernelClient, handleOfficeTaskPaneKeyDown, isOfficeKernelSpreadsheetError, normalizeOfficeFontFamily, officeFontFamilies, officeFontFamilyLabel, office_kernel_spreadsheet_protocol_OFFICE_KERNEL_SPREADSHEET_MAX_ROWS, useOfficeDialog, useOfficeTaskPaneEscape, useOfficeTaskPaneModal };
|