@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
|
@@ -0,0 +1,2470 @@
|
|
|
1
|
+
import extension_color from "@tiptap/extension-color";
|
|
2
|
+
import extension_highlight from "@tiptap/extension-highlight";
|
|
3
|
+
import { TableKit, createTable } from "@tiptap/extension-table";
|
|
4
|
+
import extension_text_align from "@tiptap/extension-text-align";
|
|
5
|
+
import { TextStyle } from "@tiptap/extension-text-style";
|
|
6
|
+
import font_family from "@tiptap/extension-text-style/font-family";
|
|
7
|
+
import font_size from "@tiptap/extension-text-style/font-size";
|
|
8
|
+
import extension_underline from "@tiptap/extension-underline";
|
|
9
|
+
import starter_kit from "@tiptap/starter-kit";
|
|
10
|
+
import { Extension, Mark, Node, mergeAttributes } from "@tiptap/core";
|
|
11
|
+
import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
|
|
12
|
+
import { DOMParser as model_DOMParser, Fragment, Slice } from "@tiptap/pm/model";
|
|
13
|
+
import extension_subscript from "@tiptap/extension-subscript";
|
|
14
|
+
import extension_superscript from "@tiptap/extension-superscript";
|
|
15
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
16
|
+
import { BulletList, OrderedList } from "@tiptap/extension-list";
|
|
17
|
+
import { documentFieldLabel, documentSections, documentCaptionLabel, documentCaptionKind, renameDocumentCitationTagInInstruction, documentNoteReferenceKeys, collectDocumentNotes, documentSectionNodeAttributes, syncDocumentContentFromHtml, documentFieldInstruction, documentCitationTagsFromInstruction, documentCitationInstruction, documentCitationTags, documentFieldKind, documentSectionDomAttributes, documentFieldDisplay, docxDocumentFieldKind, renderDocumentBibliographyHtml, documentSectionLayoutFromNodeAttributes, documentNoteKey, documentCaptionDisplay, resolveDocumentCitation, removeDocumentNoteDefinitions, resolveDocumentFieldsHtml, documentNoteKind } from "./4704.js";
|
|
18
|
+
import { createOfficeId as createWorkId } from "./1134.js";
|
|
19
|
+
import { DocumentParagraphTabStops, DocumentImage, normalizeDocumentTabStops } from "./0~8155.js";
|
|
20
|
+
import { DocumentTable, DocumentTableCell, DocumentTableHeader, DocumentTableRow, DocumentTableSizing, DocumentTableFormatting } from "./0~6552.js";
|
|
21
|
+
import { DocumentParagraphFormatting } from "./0~work-document-paragraph-formatting.js";
|
|
22
|
+
function activeDocumentSection(editor) {
|
|
23
|
+
return activeDocumentSectionFromState(editor.state);
|
|
24
|
+
}
|
|
25
|
+
function activeDocumentSectionFromState(state) {
|
|
26
|
+
const { doc, selection } = state;
|
|
27
|
+
let position = null;
|
|
28
|
+
let node = null;
|
|
29
|
+
for(let depth = selection.$from.depth; depth > 0; depth -= 1){
|
|
30
|
+
const candidate = selection.$from.node(depth);
|
|
31
|
+
if ('documentSection' === candidate.type.name) {
|
|
32
|
+
position = selection.$from.before(depth);
|
|
33
|
+
node = candidate;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const sections = directDocumentSections(doc);
|
|
38
|
+
if (!node || null === position) {
|
|
39
|
+
const containing = sections.find((section)=>selection.from >= section.position && selection.from <= section.position + section.node.nodeSize);
|
|
40
|
+
if (!containing) return null;
|
|
41
|
+
position = containing.position;
|
|
42
|
+
node = containing.node;
|
|
43
|
+
}
|
|
44
|
+
const index = sections.findIndex((section)=>section.position === position);
|
|
45
|
+
if (index < 0) return null;
|
|
46
|
+
const id = 'string' == typeof node.attrs.id && node.attrs.id ? node.attrs.id : `document-section-${index + 1}`;
|
|
47
|
+
return {
|
|
48
|
+
id,
|
|
49
|
+
index,
|
|
50
|
+
count: sections.length,
|
|
51
|
+
position,
|
|
52
|
+
node,
|
|
53
|
+
layout: documentSectionLayoutFromNodeAttributes(node.attrs)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function updateActiveDocumentSection(layout, commandContext) {
|
|
57
|
+
const state = commandContext.state;
|
|
58
|
+
const section = activeDocumentSectionFromState(state);
|
|
59
|
+
if (!section) return false;
|
|
60
|
+
return updateDocumentSection(section.id, layout, commandContext);
|
|
61
|
+
}
|
|
62
|
+
function documentSectionById(editor, sectionId) {
|
|
63
|
+
return documentSectionByIdInDocument(editor.state.doc, sectionId);
|
|
64
|
+
}
|
|
65
|
+
function updateDocumentSection(sectionId, layout, commandContext) {
|
|
66
|
+
const state = commandContext.state;
|
|
67
|
+
const section = documentSectionByIdInDocument(state.doc, sectionId);
|
|
68
|
+
if (!section) return false;
|
|
69
|
+
commandContext.tr.setNodeMarkup(section.position, void 0, documentSectionNodeAttributes(layout, section.id));
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
function insertDocumentSection(editor, breakAfter, commandContext) {
|
|
73
|
+
const state = commandContext.state;
|
|
74
|
+
const section = activeDocumentSectionFromState(state);
|
|
75
|
+
const sectionType = editor.schema.nodes.documentSection;
|
|
76
|
+
const paragraphType = editor.schema.nodes.paragraph;
|
|
77
|
+
if (!section || !sectionType || !paragraphType) return false;
|
|
78
|
+
const children = [];
|
|
79
|
+
section.node.forEach((child)=>{
|
|
80
|
+
children.push(child);
|
|
81
|
+
});
|
|
82
|
+
const activeChildIndex = sectionChildIndex(section, state.selection.from);
|
|
83
|
+
const currentChildren = children.slice(0, activeChildIndex + 1);
|
|
84
|
+
const followingChildren = children.slice(activeChildIndex + 1);
|
|
85
|
+
if (!currentChildren.length) currentChildren.push(paragraphType.create());
|
|
86
|
+
if (!followingChildren.length) followingChildren.push(paragraphType.create());
|
|
87
|
+
const currentLayout = {
|
|
88
|
+
...section.layout,
|
|
89
|
+
breakAfter
|
|
90
|
+
};
|
|
91
|
+
const nextLayout = {
|
|
92
|
+
...section.layout,
|
|
93
|
+
margins: {
|
|
94
|
+
...section.layout.margins
|
|
95
|
+
},
|
|
96
|
+
columns: {
|
|
97
|
+
...section.layout.columns
|
|
98
|
+
},
|
|
99
|
+
breakAfter: 'nextPage',
|
|
100
|
+
pageNumberStart: void 0
|
|
101
|
+
};
|
|
102
|
+
const currentNode = sectionType.create(documentSectionNodeAttributes(currentLayout, section.id), Fragment.fromArray(currentChildren));
|
|
103
|
+
const nextNode = sectionType.create(documentSectionNodeAttributes(nextLayout, createWorkId('section')), Fragment.fromArray(followingChildren));
|
|
104
|
+
const transaction = commandContext.tr.replaceWith(section.position, section.position + section.node.nodeSize, Fragment.fromArray([
|
|
105
|
+
currentNode,
|
|
106
|
+
nextNode
|
|
107
|
+
]));
|
|
108
|
+
const nextPosition = section.position + currentNode.nodeSize + 1;
|
|
109
|
+
transaction.setSelection(TextSelection.near(transaction.doc.resolve(nextPosition)));
|
|
110
|
+
transaction.scrollIntoView();
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
function mergeDocumentSectionWithPrevious(_editor, commandContext) {
|
|
114
|
+
const state = commandContext.state;
|
|
115
|
+
const section = activeDocumentSectionFromState(state);
|
|
116
|
+
if (!section || 0 === section.index) return false;
|
|
117
|
+
const sections = directDocumentSections(state.doc);
|
|
118
|
+
const previous = sections[section.index - 1];
|
|
119
|
+
const merged = previous.node.type.create(previous.node.attrs, previous.node.content.append(section.node.content), previous.node.marks);
|
|
120
|
+
const transaction = commandContext.tr.replaceWith(previous.position, section.position + section.node.nodeSize, merged);
|
|
121
|
+
const selectionPosition = Math.min(previous.position + previous.node.nodeSize - 1, transaction.doc.content.size);
|
|
122
|
+
transaction.setSelection(TextSelection.near(transaction.doc.resolve(selectionPosition)));
|
|
123
|
+
transaction.scrollIntoView();
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
function documentSectionByIdInDocument(document1, sectionId) {
|
|
127
|
+
const sections = directDocumentSections(document1);
|
|
128
|
+
const index = sections.findIndex(({ node }, candidateIndex)=>{
|
|
129
|
+
const id = 'string' == typeof node.attrs.id && node.attrs.id ? node.attrs.id : `document-section-${candidateIndex + 1}`;
|
|
130
|
+
return id === sectionId;
|
|
131
|
+
});
|
|
132
|
+
const section = sections[index];
|
|
133
|
+
if (!section) return null;
|
|
134
|
+
return {
|
|
135
|
+
id: sectionId,
|
|
136
|
+
index,
|
|
137
|
+
count: sections.length,
|
|
138
|
+
position: section.position,
|
|
139
|
+
node: section.node,
|
|
140
|
+
layout: documentSectionLayoutFromNodeAttributes(section.node.attrs)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function directDocumentSections(document1) {
|
|
144
|
+
const sections = [];
|
|
145
|
+
document1.forEach((node, position)=>{
|
|
146
|
+
if ('documentSection' === node.type.name) sections.push({
|
|
147
|
+
position,
|
|
148
|
+
node
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
return sections;
|
|
152
|
+
}
|
|
153
|
+
function sectionChildIndex(section, selectionPosition) {
|
|
154
|
+
const relativePosition = Math.max(0, selectionPosition - section.position - 1);
|
|
155
|
+
let activeIndex = 0;
|
|
156
|
+
section.node.forEach((_child, offset, index)=>{
|
|
157
|
+
if (relativePosition >= offset) activeIndex = index;
|
|
158
|
+
});
|
|
159
|
+
return activeIndex;
|
|
160
|
+
}
|
|
161
|
+
const DocumentCaption = Node.create({
|
|
162
|
+
name: 'documentCaption',
|
|
163
|
+
priority: 110,
|
|
164
|
+
group: 'block',
|
|
165
|
+
content: 'inline*',
|
|
166
|
+
defining: true,
|
|
167
|
+
addCommands () {
|
|
168
|
+
return {
|
|
169
|
+
insertDocumentCaption: (kind, title)=>(props)=>insertDocumentCaptionCommand(props, kind, title),
|
|
170
|
+
insertDocumentCrossReference: (target)=>(props)=>insertDocumentCrossReferenceCommand(props, target)
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
addKeyboardShortcuts () {
|
|
174
|
+
return {
|
|
175
|
+
Backspace: ()=>deleteEmptyDocumentCaption(this.editor)
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
addProseMirrorPlugins () {
|
|
179
|
+
return [
|
|
180
|
+
new Plugin({
|
|
181
|
+
appendTransaction (transactions, _oldState, newState) {
|
|
182
|
+
if (!transactions.some((transaction)=>transaction.docChanged)) return null;
|
|
183
|
+
return synchronizeDocumentCaptionState(newState);
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
];
|
|
187
|
+
},
|
|
188
|
+
addAttributes () {
|
|
189
|
+
return {
|
|
190
|
+
id: hiddenAttribute(''),
|
|
191
|
+
kind: hiddenAttribute('figure'),
|
|
192
|
+
number: hiddenAttribute(1),
|
|
193
|
+
accessibleName: hiddenAttribute('')
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
parseHTML () {
|
|
197
|
+
return [
|
|
198
|
+
{
|
|
199
|
+
tag: 'figcaption[data-document-caption]',
|
|
200
|
+
getAttrs: (node)=>{
|
|
201
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
202
|
+
return {
|
|
203
|
+
id: node.dataset.captionId ?? '',
|
|
204
|
+
kind: documentCaptionKind(node.dataset.captionKind) ?? 'figure',
|
|
205
|
+
number: positiveInteger(node.dataset.captionNumber),
|
|
206
|
+
accessibleName: node.getAttribute('aria-label') ?? ''
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
];
|
|
211
|
+
},
|
|
212
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
213
|
+
const kind = documentCaptionKind(node.attrs.kind) ?? 'figure';
|
|
214
|
+
const number = positiveInteger(node.attrs.number);
|
|
215
|
+
const accessibleName = documentCaptionAccessibleName(kind, number, node.textContent);
|
|
216
|
+
return [
|
|
217
|
+
'figcaption',
|
|
218
|
+
mergeAttributes(HTMLAttributes, {
|
|
219
|
+
'data-document-caption': 'true',
|
|
220
|
+
'data-caption-id': 'string' == typeof node.attrs.id ? node.attrs.id : '',
|
|
221
|
+
'data-caption-kind': kind,
|
|
222
|
+
'data-caption-number': String(number),
|
|
223
|
+
'data-caption-label': documentCaptionLabel(kind),
|
|
224
|
+
'aria-label': accessibleName,
|
|
225
|
+
class: 'work-document-caption'
|
|
226
|
+
}),
|
|
227
|
+
0
|
|
228
|
+
];
|
|
229
|
+
},
|
|
230
|
+
renderText ({ node }) {
|
|
231
|
+
const kind = documentCaptionKind(node.attrs.kind) ?? 'figure';
|
|
232
|
+
return `${documentCaptionDisplay(kind, positiveInteger(node.attrs.number))} ${node.textContent}`.trim();
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
const DocumentCrossReference = Node.create({
|
|
236
|
+
name: 'documentCrossReference',
|
|
237
|
+
inline: true,
|
|
238
|
+
group: 'inline',
|
|
239
|
+
atom: true,
|
|
240
|
+
selectable: true,
|
|
241
|
+
addAttributes () {
|
|
242
|
+
return {
|
|
243
|
+
targetId: hiddenAttribute(''),
|
|
244
|
+
kind: hiddenAttribute('figure'),
|
|
245
|
+
number: hiddenAttribute(1),
|
|
246
|
+
orphaned: hiddenAttribute(false)
|
|
247
|
+
};
|
|
248
|
+
},
|
|
249
|
+
parseHTML () {
|
|
250
|
+
return [
|
|
251
|
+
{
|
|
252
|
+
tag: 'span[data-document-cross-reference]',
|
|
253
|
+
getAttrs: (node)=>{
|
|
254
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
255
|
+
return {
|
|
256
|
+
targetId: node.dataset.referenceTargetId ?? '',
|
|
257
|
+
kind: documentCaptionKind(node.dataset.captionKind) ?? 'figure',
|
|
258
|
+
number: positiveInteger(node.dataset.captionNumber),
|
|
259
|
+
orphaned: 'true' === node.dataset.referenceOrphaned
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
];
|
|
264
|
+
},
|
|
265
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
266
|
+
const kind = documentCaptionKind(node.attrs.kind) ?? 'figure';
|
|
267
|
+
const number = positiveInteger(node.attrs.number);
|
|
268
|
+
const orphaned = Boolean(node.attrs.orphaned);
|
|
269
|
+
return [
|
|
270
|
+
'span',
|
|
271
|
+
mergeAttributes(HTMLAttributes, {
|
|
272
|
+
'data-document-cross-reference': 'true',
|
|
273
|
+
'data-reference-target-id': 'string' == typeof node.attrs.targetId ? node.attrs.targetId : '',
|
|
274
|
+
'data-caption-kind': kind,
|
|
275
|
+
'data-caption-number': String(number),
|
|
276
|
+
'data-caption-label': documentCaptionLabel(kind),
|
|
277
|
+
'data-reference-orphaned': orphaned ? 'true' : void 0,
|
|
278
|
+
class: 'work-document-cross-reference'
|
|
279
|
+
}),
|
|
280
|
+
orphaned ? '引用缺失' : documentCaptionDisplay(kind, number)
|
|
281
|
+
];
|
|
282
|
+
},
|
|
283
|
+
renderText ({ node }) {
|
|
284
|
+
if (node.attrs.orphaned) return '引用缺失';
|
|
285
|
+
const kind = documentCaptionKind(node.attrs.kind) ?? 'figure';
|
|
286
|
+
return documentCaptionDisplay(kind, positiveInteger(node.attrs.number));
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
function editorDocumentCaptionTargets(editor) {
|
|
290
|
+
return documentCaptionTargets(editor.state.doc);
|
|
291
|
+
}
|
|
292
|
+
function insertDocumentCaptionCommand({ dispatch, editor, state, tr }, kind, title) {
|
|
293
|
+
const section = activeDocumentSectionFromState(state);
|
|
294
|
+
const captionType = editor.schema.nodes.documentCaption;
|
|
295
|
+
const paragraphType = editor.schema.nodes.paragraph;
|
|
296
|
+
if (!section || !captionType || !paragraphType || selectionInsideNode(state, 'documentCaption')) return false;
|
|
297
|
+
const child = activeSectionChild(section, state.selection.from);
|
|
298
|
+
if (!child) return false;
|
|
299
|
+
if (!dispatch) return true;
|
|
300
|
+
const id = createWorkId(`caption-${kind}`);
|
|
301
|
+
const number = nextCaptionNumber(state.doc, kind);
|
|
302
|
+
const normalizedTitle = title.trim();
|
|
303
|
+
const caption = captionType.create({
|
|
304
|
+
id,
|
|
305
|
+
kind,
|
|
306
|
+
number,
|
|
307
|
+
accessibleName: documentCaptionAccessibleName(kind, number, normalizedTitle)
|
|
308
|
+
}, normalizedTitle ? editor.schema.text(normalizedTitle) : void 0);
|
|
309
|
+
const insertPosition = section.position + 1 + child.offset + child.nodeSize;
|
|
310
|
+
tr.insert(insertPosition, caption);
|
|
311
|
+
let selectionPosition = insertPosition + caption.nodeSize;
|
|
312
|
+
if (child.index === section.node.childCount - 1) {
|
|
313
|
+
tr.insert(selectionPosition, paragraphType.create());
|
|
314
|
+
selectionPosition += 1;
|
|
315
|
+
}
|
|
316
|
+
tr.setSelection(TextSelection.near(tr.doc.resolve(selectionPosition)));
|
|
317
|
+
tr.scrollIntoView();
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
function insertDocumentCrossReferenceCommand({ dispatch, editor, tr }, target) {
|
|
321
|
+
const referenceType = editor.schema.nodes.documentCrossReference;
|
|
322
|
+
if (!referenceType || !target.id.trim()) return false;
|
|
323
|
+
if (!dispatch) return true;
|
|
324
|
+
tr.replaceSelectionWith(referenceType.create({
|
|
325
|
+
targetId: target.id,
|
|
326
|
+
kind: target.kind,
|
|
327
|
+
number: target.number,
|
|
328
|
+
orphaned: false
|
|
329
|
+
}), false);
|
|
330
|
+
tr.scrollIntoView();
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
function synchronizeDocumentCaptionState(state) {
|
|
334
|
+
const counters = {
|
|
335
|
+
figure: 0,
|
|
336
|
+
table: 0
|
|
337
|
+
};
|
|
338
|
+
const targets = new Map();
|
|
339
|
+
const transaction = state.tr;
|
|
340
|
+
let changed = false;
|
|
341
|
+
state.doc.descendants((node, position)=>{
|
|
342
|
+
if ('documentCaption' !== node.type.name) return;
|
|
343
|
+
const kind = documentCaptionKind(node.attrs.kind) ?? 'figure';
|
|
344
|
+
counters[kind] += 1;
|
|
345
|
+
const number = counters[kind];
|
|
346
|
+
const accessibleName = documentCaptionAccessibleName(kind, number, node.textContent);
|
|
347
|
+
const id = 'string' == typeof node.attrs.id ? node.attrs.id.trim() : '';
|
|
348
|
+
if (id && !targets.has(id)) targets.set(id, {
|
|
349
|
+
kind,
|
|
350
|
+
number
|
|
351
|
+
});
|
|
352
|
+
if (node.attrs.kind === kind && node.attrs.number === number && node.attrs.accessibleName === accessibleName) return;
|
|
353
|
+
transaction.setNodeMarkup(position, void 0, {
|
|
354
|
+
...node.attrs,
|
|
355
|
+
kind,
|
|
356
|
+
number,
|
|
357
|
+
accessibleName
|
|
358
|
+
});
|
|
359
|
+
changed = true;
|
|
360
|
+
});
|
|
361
|
+
state.doc.descendants((node, position)=>{
|
|
362
|
+
if ('documentCrossReference' !== node.type.name) return;
|
|
363
|
+
const targetId = 'string' == typeof node.attrs.targetId ? node.attrs.targetId.trim() : '';
|
|
364
|
+
const target = targets.get(targetId);
|
|
365
|
+
const kind = target?.kind ?? documentCaptionKind(node.attrs.kind) ?? 'figure';
|
|
366
|
+
const number = target?.number ?? positiveInteger(node.attrs.number);
|
|
367
|
+
const orphaned = !target;
|
|
368
|
+
if (node.attrs.targetId === targetId && node.attrs.kind === kind && node.attrs.number === number && node.attrs.orphaned === orphaned) return;
|
|
369
|
+
transaction.setNodeMarkup(position, void 0, {
|
|
370
|
+
...node.attrs,
|
|
371
|
+
targetId,
|
|
372
|
+
kind,
|
|
373
|
+
number,
|
|
374
|
+
orphaned
|
|
375
|
+
});
|
|
376
|
+
changed = true;
|
|
377
|
+
});
|
|
378
|
+
return changed ? transaction : null;
|
|
379
|
+
}
|
|
380
|
+
function deleteEmptyDocumentCaption(editor) {
|
|
381
|
+
const caption = emptyDocumentCaptionAtSelection(editor);
|
|
382
|
+
if (!caption) return false;
|
|
383
|
+
const transaction = editor.state.tr.delete(caption.position, caption.position + caption.nodeSize);
|
|
384
|
+
transaction.setSelection(TextSelection.near(transaction.doc.resolve(Math.min(caption.position, transaction.doc.content.size)), -1));
|
|
385
|
+
editor.view.dispatch(transaction.scrollIntoView());
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
function emptyDocumentCaptionAtSelection(editor) {
|
|
389
|
+
const { selection } = editor.state;
|
|
390
|
+
if (selection.empty) for(let depth = selection.$from.depth; depth > 0; depth -= 1){
|
|
391
|
+
const node = selection.$from.node(depth);
|
|
392
|
+
if ('documentCaption' === node.type.name) return 0 === node.content.size ? {
|
|
393
|
+
position: selection.$from.before(depth),
|
|
394
|
+
nodeSize: node.nodeSize
|
|
395
|
+
} : null;
|
|
396
|
+
}
|
|
397
|
+
const domSelection = editor.view.dom.ownerDocument.getSelection();
|
|
398
|
+
const anchor = domSelection?.anchorNode;
|
|
399
|
+
const anchorElement = anchor instanceof HTMLElement ? anchor : anchor?.parentElement;
|
|
400
|
+
const captionElement = anchorElement?.closest('figcaption[data-document-caption]');
|
|
401
|
+
const id = captionElement?.dataset.captionId?.trim();
|
|
402
|
+
if (!captionElement || !id || !editor.view.dom.contains(captionElement)) return null;
|
|
403
|
+
let match = null;
|
|
404
|
+
editor.state.doc.descendants((node, position)=>{
|
|
405
|
+
if (match || 'documentCaption' !== node.type.name || node.attrs.id !== id || node.content.size > 0) return;
|
|
406
|
+
match = {
|
|
407
|
+
position,
|
|
408
|
+
nodeSize: node.nodeSize
|
|
409
|
+
};
|
|
410
|
+
});
|
|
411
|
+
return match;
|
|
412
|
+
}
|
|
413
|
+
function documentCaptionAccessibleName(kind, number, title) {
|
|
414
|
+
const display = documentCaptionDisplay(kind, number);
|
|
415
|
+
const normalizedTitle = title.trim();
|
|
416
|
+
return normalizedTitle ? `${display} ${normalizedTitle}` : display;
|
|
417
|
+
}
|
|
418
|
+
function documentCaptionTargets(document1) {
|
|
419
|
+
const targets = [];
|
|
420
|
+
document1.descendants((node)=>{
|
|
421
|
+
if ('documentCaption' !== node.type.name) return;
|
|
422
|
+
const id = 'string' == typeof node.attrs.id ? node.attrs.id.trim() : '';
|
|
423
|
+
const kind = documentCaptionKind(node.attrs.kind);
|
|
424
|
+
if (!id || !kind) return;
|
|
425
|
+
const number = positiveInteger(node.attrs.number);
|
|
426
|
+
targets.push({
|
|
427
|
+
id,
|
|
428
|
+
kind,
|
|
429
|
+
number,
|
|
430
|
+
label: 'figure' === kind ? '图' : '表',
|
|
431
|
+
title: node.textContent.trim(),
|
|
432
|
+
display: documentCaptionDisplay(kind, number)
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
return targets;
|
|
436
|
+
}
|
|
437
|
+
function nextCaptionNumber(document1, kind) {
|
|
438
|
+
return documentCaptionTargets(document1).filter((caption)=>caption.kind === kind).length + 1;
|
|
439
|
+
}
|
|
440
|
+
function activeSectionChild(section, selectionPosition) {
|
|
441
|
+
const relativePosition = Math.max(0, selectionPosition - section.position - 1);
|
|
442
|
+
let active = null;
|
|
443
|
+
section.node.forEach((node, offset, index)=>{
|
|
444
|
+
if (relativePosition >= offset) active = {
|
|
445
|
+
index,
|
|
446
|
+
offset,
|
|
447
|
+
nodeSize: node.nodeSize
|
|
448
|
+
};
|
|
449
|
+
});
|
|
450
|
+
return active;
|
|
451
|
+
}
|
|
452
|
+
function selectionInsideNode(state, nodeName) {
|
|
453
|
+
for(let depth = state.selection.$from.depth; depth > 0; depth -= 1)if (state.selection.$from.node(depth).type.name === nodeName) return true;
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
function hiddenAttribute(defaultValue) {
|
|
457
|
+
return {
|
|
458
|
+
default: defaultValue,
|
|
459
|
+
rendered: false
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function positiveInteger(value) {
|
|
463
|
+
const number = Number(value);
|
|
464
|
+
return Number.isSafeInteger(number) && number > 0 ? number : 1;
|
|
465
|
+
}
|
|
466
|
+
const DocumentSubscript = extension_subscript.extend({
|
|
467
|
+
excludes: "superscript",
|
|
468
|
+
addCommands () {
|
|
469
|
+
return {
|
|
470
|
+
...this.parent?.() ?? {},
|
|
471
|
+
toggleDocumentSubscript: ()=>({ chain, editor })=>{
|
|
472
|
+
const commandChain = chain().focus();
|
|
473
|
+
return editor.isActive("subscript") ? commandChain.unsetSubscript().run() : commandChain.unsetSuperscript().setSubscript().run();
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
},
|
|
477
|
+
addKeyboardShortcuts () {
|
|
478
|
+
return {
|
|
479
|
+
'Mod-,': ()=>this.editor.commands.toggleDocumentSubscript()
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
const DocumentSuperscript = extension_superscript.extend({
|
|
484
|
+
excludes: "subscript",
|
|
485
|
+
addCommands () {
|
|
486
|
+
return {
|
|
487
|
+
...this.parent?.() ?? {},
|
|
488
|
+
toggleDocumentSuperscript: ()=>({ chain, editor })=>{
|
|
489
|
+
const commandChain = chain().focus();
|
|
490
|
+
return editor.isActive("superscript") ? commandChain.unsetSuperscript().run() : commandChain.unsetSubscript().setSuperscript().run();
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
},
|
|
494
|
+
addKeyboardShortcuts () {
|
|
495
|
+
return {
|
|
496
|
+
'Mod-.': ()=>this.editor.commands.toggleDocumentSuperscript()
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
const documentChangePluginKey = new PluginKey('documentChangeTracking');
|
|
501
|
+
const CONTINUOUS_INSERTION_WINDOW_MS = 30000;
|
|
502
|
+
const DocumentChange = Mark.create({
|
|
503
|
+
name: 'documentChange',
|
|
504
|
+
priority: 1100,
|
|
505
|
+
inclusive: false,
|
|
506
|
+
keepOnSplit: false,
|
|
507
|
+
addOptions () {
|
|
508
|
+
return {
|
|
509
|
+
isTracking: ()=>false,
|
|
510
|
+
createChange: ()=>({
|
|
511
|
+
id: createDocumentChangeId(),
|
|
512
|
+
author: 'A3S Work',
|
|
513
|
+
date: new Date().toISOString()
|
|
514
|
+
}),
|
|
515
|
+
onTrackingChange: ()=>void 0
|
|
516
|
+
};
|
|
517
|
+
},
|
|
518
|
+
addAttributes () {
|
|
519
|
+
return {
|
|
520
|
+
kind: {
|
|
521
|
+
default: 'insertion',
|
|
522
|
+
parseHTML: (element)=>'del' === element.tagName.toLowerCase() ? 'deletion' : 'insertion',
|
|
523
|
+
renderHTML: (attributes)=>({
|
|
524
|
+
'data-change-kind': attributes.kind
|
|
525
|
+
})
|
|
526
|
+
},
|
|
527
|
+
id: {
|
|
528
|
+
default: '',
|
|
529
|
+
parseHTML: (element)=>element.getAttribute('data-change-id') ?? '',
|
|
530
|
+
renderHTML: (attributes)=>({
|
|
531
|
+
'data-change-id': attributes.id
|
|
532
|
+
})
|
|
533
|
+
},
|
|
534
|
+
author: {
|
|
535
|
+
default: '',
|
|
536
|
+
parseHTML: (element)=>element.getAttribute('data-change-author') ?? '',
|
|
537
|
+
renderHTML: (attributes)=>({
|
|
538
|
+
'data-change-author': attributes.author
|
|
539
|
+
})
|
|
540
|
+
},
|
|
541
|
+
date: {
|
|
542
|
+
default: '',
|
|
543
|
+
parseHTML: (element)=>element.getAttribute('data-change-date') ?? '',
|
|
544
|
+
renderHTML: (attributes)=>({
|
|
545
|
+
'data-change-date': attributes.date
|
|
546
|
+
})
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
},
|
|
550
|
+
parseHTML () {
|
|
551
|
+
return [
|
|
552
|
+
{
|
|
553
|
+
tag: 'ins[data-document-change]'
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
tag: 'del[data-document-change]'
|
|
557
|
+
}
|
|
558
|
+
];
|
|
559
|
+
},
|
|
560
|
+
renderHTML ({ mark, HTMLAttributes }) {
|
|
561
|
+
return [
|
|
562
|
+
'deletion' === mark.attrs.kind ? 'del' : 'ins',
|
|
563
|
+
mergeAttributes(HTMLAttributes, {
|
|
564
|
+
'data-document-change': 'true'
|
|
565
|
+
}),
|
|
566
|
+
0
|
|
567
|
+
];
|
|
568
|
+
},
|
|
569
|
+
addCommands () {
|
|
570
|
+
return {
|
|
571
|
+
acceptAllDocumentChanges: ()=>(props)=>resolveDocumentChangesCommand(props, this.type, 'accept') > 0,
|
|
572
|
+
acceptDocumentChange: (id)=>(props)=>resolveDocumentChangesCommand(props, this.type, 'accept', new Set([
|
|
573
|
+
id
|
|
574
|
+
])) > 0,
|
|
575
|
+
rejectAllDocumentChanges: ()=>(props)=>resolveDocumentChangesCommand(props, this.type, 'reject') > 0,
|
|
576
|
+
rejectDocumentChange: (id)=>(props)=>resolveDocumentChangesCommand(props, this.type, 'reject', new Set([
|
|
577
|
+
id
|
|
578
|
+
])) > 0,
|
|
579
|
+
replaceDocumentTextWithTrackedChange: (from, to, text)=>({ state, tr })=>{
|
|
580
|
+
if (from < 0 || to < from || to > state.doc.content.size) return false;
|
|
581
|
+
trackedReplacement(tr, state.doc, this.type, from, to, text, this.options.createChange);
|
|
582
|
+
return tr.docChanged;
|
|
583
|
+
},
|
|
584
|
+
setDocumentTrackChanges: (enabled)=>()=>{
|
|
585
|
+
if (enabled !== this.options.isTracking()) this.options.onTrackingChange(enabled);
|
|
586
|
+
return true;
|
|
587
|
+
},
|
|
588
|
+
toggleDocumentTrackChanges: ()=>()=>{
|
|
589
|
+
this.options.onTrackingChange(!this.options.isTracking());
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
},
|
|
594
|
+
addProseMirrorPlugins () {
|
|
595
|
+
const changeType = this.type;
|
|
596
|
+
const options = this.options;
|
|
597
|
+
return [
|
|
598
|
+
new Plugin({
|
|
599
|
+
key: documentChangePluginKey,
|
|
600
|
+
props: {
|
|
601
|
+
handleTextInput: (view, from, to, text)=>{
|
|
602
|
+
if (!options.isTracking()) return false;
|
|
603
|
+
const transaction = trackedReplacement(view.state.tr, view.state.doc, changeType, from, to, text, options.createChange);
|
|
604
|
+
view.dispatch(transaction);
|
|
605
|
+
return true;
|
|
606
|
+
},
|
|
607
|
+
handleKeyDown: (view, event)=>{
|
|
608
|
+
if (!options.isTracking() || event.isComposing || event.metaKey || event.ctrlKey || 'Backspace' !== event.key && 'Delete' !== event.key) return false;
|
|
609
|
+
const selection = view.state.selection;
|
|
610
|
+
const range = selection.from !== selection.to ? {
|
|
611
|
+
from: selection.from,
|
|
612
|
+
to: selection.to
|
|
613
|
+
} : adjacentTextRange(view.state.doc, selection.from, 'Backspace' === event.key ? -1 : 1);
|
|
614
|
+
if (!range) return false;
|
|
615
|
+
const transaction = view.state.tr;
|
|
616
|
+
const changed = trackDeletion(transaction, view.state.doc, changeType, range.from, range.to, changeMark(changeType, 'deletion', options.createChange));
|
|
617
|
+
if (!changed) return false;
|
|
618
|
+
const cursor = Math.min(transaction.doc.content.size, transaction.mapping.map(range.from));
|
|
619
|
+
transaction.setSelection(TextSelection.near(transaction.doc.resolve(cursor)));
|
|
620
|
+
view.dispatch(transaction);
|
|
621
|
+
return true;
|
|
622
|
+
},
|
|
623
|
+
handlePaste: (view, _event, slice)=>{
|
|
624
|
+
if (!options.isTracking()) return false;
|
|
625
|
+
const insertion = changeMark(changeType, 'insertion', options.createChange);
|
|
626
|
+
const markedSlice = new Slice(markFragment(slice.content, insertion, changeType), slice.openStart, slice.openEnd);
|
|
627
|
+
const { from, to } = view.state.selection;
|
|
628
|
+
const transaction = view.state.tr;
|
|
629
|
+
if (from !== to) trackDeletion(transaction, view.state.doc, changeType, from, to, changeMark(changeType, 'deletion', options.createChange));
|
|
630
|
+
const position = transaction.mapping.map(to, -1);
|
|
631
|
+
transaction.replace(position, position, markedSlice);
|
|
632
|
+
const cursor = Math.min(transaction.doc.content.size, position + markedSlice.size);
|
|
633
|
+
transaction.setSelection(TextSelection.near(transaction.doc.resolve(cursor)));
|
|
634
|
+
view.dispatch(transaction);
|
|
635
|
+
return true;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
})
|
|
639
|
+
];
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
function collectDocumentChanges(document1) {
|
|
643
|
+
const changes = new Map();
|
|
644
|
+
document1.descendants((node, position)=>{
|
|
645
|
+
if (!node.isText || !node.text) return;
|
|
646
|
+
const mark = documentChangeMark(node.marks);
|
|
647
|
+
if (!mark) return;
|
|
648
|
+
const kind = changeKind(mark.attrs.kind);
|
|
649
|
+
const id = stringAttribute(mark.attrs.id) || `change-at-${position}`;
|
|
650
|
+
const key = `${kind}:${id}`;
|
|
651
|
+
const current = changes.get(key);
|
|
652
|
+
if (current) {
|
|
653
|
+
current.from = Math.min(current.from, position);
|
|
654
|
+
current.to = Math.max(current.to, position + node.nodeSize);
|
|
655
|
+
current.text += node.text;
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
changes.set(key, {
|
|
659
|
+
id,
|
|
660
|
+
kind,
|
|
661
|
+
author: stringAttribute(mark.attrs.author) || '未知审阅者',
|
|
662
|
+
date: stringAttribute(mark.attrs.date),
|
|
663
|
+
from: position,
|
|
664
|
+
to: position + node.nodeSize,
|
|
665
|
+
text: node.text
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
return Array.from(changes.values()).sort((left, right)=>left.from - right.from);
|
|
669
|
+
}
|
|
670
|
+
function resolveDocumentChangesCommand({ state, tr }, type, decision, ids) {
|
|
671
|
+
const segments = documentChangeSegments(state.doc, type).filter((segment)=>!ids || ids.has(segment.id));
|
|
672
|
+
if (!segments.length) return 0;
|
|
673
|
+
const removals = [];
|
|
674
|
+
const deletions = [];
|
|
675
|
+
for (const segment of segments){
|
|
676
|
+
const remove = 'accept' === decision && 'insertion' === segment.kind || 'reject' === decision && 'deletion' === segment.kind;
|
|
677
|
+
(remove ? removals : deletions).push(segment);
|
|
678
|
+
}
|
|
679
|
+
for (const segment of removals)tr.removeMark(segment.from, segment.to, type);
|
|
680
|
+
for (const segment of deletions.sort((left, right)=>right.from - left.from))tr.delete(segment.from, segment.to);
|
|
681
|
+
return tr.docChanged ? new Set(segments.map((segment)=>segment.id)).size : 0;
|
|
682
|
+
}
|
|
683
|
+
function trackedReplacement(transaction, document1, type, from, to, text, createChange) {
|
|
684
|
+
if (from !== to) trackDeletion(transaction, document1, type, from, to, changeMark(type, 'deletion', createChange));
|
|
685
|
+
const position = transaction.mapping.map(to, -1);
|
|
686
|
+
if (text) {
|
|
687
|
+
const insertion = from === to ? continuousInsertionMark(document1, type, position, createChange) : changeMark(type, 'insertion', createChange);
|
|
688
|
+
transaction.insertText(text, position);
|
|
689
|
+
transaction.addMark(position, position + text.length, insertion);
|
|
690
|
+
}
|
|
691
|
+
const cursor = Math.min(transaction.doc.content.size, position + text.length);
|
|
692
|
+
transaction.setSelection(TextSelection.near(transaction.doc.resolve(cursor)));
|
|
693
|
+
return transaction;
|
|
694
|
+
}
|
|
695
|
+
function trackDeletion(transaction, document1, type, from, to, deletion) {
|
|
696
|
+
const segments = textSegments(document1, type, from, to);
|
|
697
|
+
if (!segments.length) return false;
|
|
698
|
+
for (const segment of segments)if (!segment.kind) transaction.addMark(segment.from, segment.to, deletion);
|
|
699
|
+
for (const segment of segments.filter((segment)=>'insertion' === segment.kind).sort((left, right)=>right.from - left.from))transaction.delete(segment.from, segment.to);
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
function textSegments(document1, type, from, to) {
|
|
703
|
+
const segments = [];
|
|
704
|
+
document1.nodesBetween(from, to, (node, position)=>{
|
|
705
|
+
if (!node.isText) return;
|
|
706
|
+
const start = Math.max(from, position);
|
|
707
|
+
const end = Math.min(to, position + node.nodeSize);
|
|
708
|
+
if (start >= end) return;
|
|
709
|
+
const mark = node.marks.find((candidate)=>candidate.type === type);
|
|
710
|
+
segments.push({
|
|
711
|
+
from: start,
|
|
712
|
+
to: end,
|
|
713
|
+
kind: mark ? changeKind(mark.attrs.kind) : null
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
return segments;
|
|
717
|
+
}
|
|
718
|
+
function documentChangeSegments(document1, type) {
|
|
719
|
+
const segments = [];
|
|
720
|
+
document1.descendants((node, position)=>{
|
|
721
|
+
if (!node.isText) return;
|
|
722
|
+
const mark = node.marks.find((candidate)=>candidate.type === type);
|
|
723
|
+
if (!mark) return;
|
|
724
|
+
segments.push({
|
|
725
|
+
id: stringAttribute(mark.attrs.id) || `change-at-${position}`,
|
|
726
|
+
kind: changeKind(mark.attrs.kind),
|
|
727
|
+
from: position,
|
|
728
|
+
to: position + node.nodeSize
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
return segments;
|
|
732
|
+
}
|
|
733
|
+
function markFragment(fragment, insertion, type) {
|
|
734
|
+
const nodes = [];
|
|
735
|
+
fragment.forEach((node)=>{
|
|
736
|
+
if (node.isText) nodes.push(node.mark([
|
|
737
|
+
...node.marks.filter((mark)=>mark.type !== type),
|
|
738
|
+
insertion
|
|
739
|
+
]));
|
|
740
|
+
else if (node.content.size) nodes.push(node.copy(markFragment(node.content, insertion, type)));
|
|
741
|
+
else nodes.push(node);
|
|
742
|
+
});
|
|
743
|
+
return Fragment.fromArray(nodes);
|
|
744
|
+
}
|
|
745
|
+
function adjacentTextRange(document1, position, direction) {
|
|
746
|
+
const resolved = document1.resolve(position);
|
|
747
|
+
const node = direction < 0 ? resolved.nodeBefore : resolved.nodeAfter;
|
|
748
|
+
if (!node?.isText || !node.text) return null;
|
|
749
|
+
const character = direction < 0 ? Array.from(node.text).at(-1) : Array.from(node.text).at(0);
|
|
750
|
+
if (!character) return null;
|
|
751
|
+
return direction < 0 ? {
|
|
752
|
+
from: position - character.length,
|
|
753
|
+
to: position
|
|
754
|
+
} : {
|
|
755
|
+
from: position,
|
|
756
|
+
to: position + character.length
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
function changeMark(type, kind, createChange) {
|
|
760
|
+
const identity = createChange(kind);
|
|
761
|
+
return type.create({
|
|
762
|
+
kind,
|
|
763
|
+
id: identity.id || createDocumentChangeId(),
|
|
764
|
+
author: identity.author || 'A3S Work',
|
|
765
|
+
date: identity.date || new Date().toISOString()
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
function continuousInsertionMark(document1, type, position, createChange) {
|
|
769
|
+
const next = changeMark(type, 'insertion', createChange);
|
|
770
|
+
const previousNode = document1.resolve(position).nodeBefore;
|
|
771
|
+
const previous = previousNode?.marks.find((mark)=>mark.type === type && 'insertion' === changeKind(mark.attrs.kind));
|
|
772
|
+
if (!previous) return next;
|
|
773
|
+
if (stringAttribute(previous.attrs.author) !== stringAttribute(next.attrs.author)) return next;
|
|
774
|
+
const previousTime = Date.parse(stringAttribute(previous.attrs.date));
|
|
775
|
+
const nextTime = Date.parse(stringAttribute(next.attrs.date));
|
|
776
|
+
if (!Number.isFinite(previousTime) || !Number.isFinite(nextTime) || Math.abs(nextTime - previousTime) > CONTINUOUS_INSERTION_WINDOW_MS) return next;
|
|
777
|
+
return previous;
|
|
778
|
+
}
|
|
779
|
+
function documentChangeMark(marks) {
|
|
780
|
+
return marks.find((mark)=>'documentChange' === mark.type.name);
|
|
781
|
+
}
|
|
782
|
+
function changeKind(value) {
|
|
783
|
+
return 'deletion' === value ? 'deletion' : 'insertion';
|
|
784
|
+
}
|
|
785
|
+
function stringAttribute(value) {
|
|
786
|
+
return 'string' == typeof value ? value : '';
|
|
787
|
+
}
|
|
788
|
+
function createDocumentChangeId() {
|
|
789
|
+
const random = "u" > typeof crypto && 'function' == typeof crypto.randomUUID ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
790
|
+
return `change-${random}`;
|
|
791
|
+
}
|
|
792
|
+
const DocumentCitation = Node.create({
|
|
793
|
+
name: 'documentCitation',
|
|
794
|
+
inline: true,
|
|
795
|
+
group: 'inline',
|
|
796
|
+
atom: true,
|
|
797
|
+
selectable: true,
|
|
798
|
+
addOptions () {
|
|
799
|
+
return {
|
|
800
|
+
getContent: ()=>null,
|
|
801
|
+
onContentChange: ()=>void 0
|
|
802
|
+
};
|
|
803
|
+
},
|
|
804
|
+
addCommands () {
|
|
805
|
+
return {
|
|
806
|
+
insertDocumentCitation: (source, bibliography)=>(props)=>insertDocumentCitationCommand(props, source, bibliography),
|
|
807
|
+
insertDocumentBibliography: (bibliography)=>(props)=>insertDocumentBibliographyCommand(props, bibliography),
|
|
808
|
+
refreshDocumentCitations: (content)=>(props)=>refreshDocumentCitationsCommand(props, content),
|
|
809
|
+
renameDocumentCitationTag: (previousTag, nextTag)=>(props)=>renameDocumentCitationTagCommand(props, previousTag, nextTag),
|
|
810
|
+
setDocumentBibliography: (bibliography, renamedTag)=>({ dispatch, editor })=>{
|
|
811
|
+
const content = this.options.getContent();
|
|
812
|
+
if (!content) return false;
|
|
813
|
+
if (!dispatch) return true;
|
|
814
|
+
const next = {
|
|
815
|
+
...content,
|
|
816
|
+
bibliography
|
|
817
|
+
};
|
|
818
|
+
this.options.onContentChange(next);
|
|
819
|
+
const chain = editor.chain();
|
|
820
|
+
if (renamedTag) chain.renameDocumentCitationTag(renamedTag.previous, renamedTag.next);
|
|
821
|
+
chain.refreshDocumentCitations(next).run();
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
},
|
|
826
|
+
addAttributes () {
|
|
827
|
+
return {
|
|
828
|
+
id: work_document_citation_nodes_hiddenAttribute(''),
|
|
829
|
+
tags: work_document_citation_nodes_hiddenAttribute(''),
|
|
830
|
+
instruction: work_document_citation_nodes_hiddenAttribute(''),
|
|
831
|
+
display: work_document_citation_nodes_hiddenAttribute(''),
|
|
832
|
+
orphaned: work_document_citation_nodes_hiddenAttribute(false)
|
|
833
|
+
};
|
|
834
|
+
},
|
|
835
|
+
parseHTML () {
|
|
836
|
+
return [
|
|
837
|
+
{
|
|
838
|
+
tag: 'span[data-document-citation]',
|
|
839
|
+
getAttrs: (node)=>{
|
|
840
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
841
|
+
const instruction = node.dataset.citationInstruction?.trim() ?? '';
|
|
842
|
+
const tags = documentCitationTags(node.dataset.citationTags);
|
|
843
|
+
const resolvedTags = tags.length ? tags : documentCitationTagsFromInstruction(instruction);
|
|
844
|
+
return {
|
|
845
|
+
id: node.dataset.citationId ?? '',
|
|
846
|
+
tags: resolvedTags.join(' '),
|
|
847
|
+
instruction: instruction || documentCitationInstruction(resolvedTags),
|
|
848
|
+
display: node.dataset.citationDisplay?.trim() || node.textContent?.trim() || '缺失引文',
|
|
849
|
+
orphaned: 'true' === node.dataset.citationOrphaned
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
];
|
|
854
|
+
},
|
|
855
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
856
|
+
const tags = 'string' == typeof node.attrs.tags ? documentCitationTags(node.attrs.tags) : [];
|
|
857
|
+
const instruction = 'string' == typeof node.attrs.instruction ? node.attrs.instruction.trim() : '';
|
|
858
|
+
const display = 'string' == typeof node.attrs.display && node.attrs.display.trim() ? node.attrs.display.trim() : '缺失引文';
|
|
859
|
+
const orphaned = Boolean(node.attrs.orphaned);
|
|
860
|
+
return [
|
|
861
|
+
'span',
|
|
862
|
+
mergeAttributes(HTMLAttributes, {
|
|
863
|
+
'data-document-citation': 'true',
|
|
864
|
+
'data-citation-id': 'string' == typeof node.attrs.id ? node.attrs.id : '',
|
|
865
|
+
'data-citation-tags': tags.join(' '),
|
|
866
|
+
'data-citation-instruction': instruction || documentCitationInstruction(tags),
|
|
867
|
+
'data-citation-display': display,
|
|
868
|
+
'data-citation-orphaned': orphaned ? 'true' : void 0,
|
|
869
|
+
class: 'work-document-citation',
|
|
870
|
+
title: tags.length ? `引文:${tags.join('、')}` : '缺失引文'
|
|
871
|
+
}),
|
|
872
|
+
display
|
|
873
|
+
];
|
|
874
|
+
},
|
|
875
|
+
renderText ({ node }) {
|
|
876
|
+
return 'string' == typeof node.attrs.display && node.attrs.display.trim() ? node.attrs.display.trim() : '缺失引文';
|
|
877
|
+
}
|
|
878
|
+
});
|
|
879
|
+
const DocumentBibliography = Node.create({
|
|
880
|
+
name: 'documentBibliography',
|
|
881
|
+
group: 'block',
|
|
882
|
+
content: 'block+',
|
|
883
|
+
atom: true,
|
|
884
|
+
selectable: true,
|
|
885
|
+
defining: true,
|
|
886
|
+
isolating: true,
|
|
887
|
+
addAttributes () {
|
|
888
|
+
return {
|
|
889
|
+
id: work_document_citation_nodes_hiddenAttribute('document-bibliography-1'),
|
|
890
|
+
style: work_document_citation_nodes_hiddenAttribute('apa')
|
|
891
|
+
};
|
|
892
|
+
},
|
|
893
|
+
parseHTML () {
|
|
894
|
+
return [
|
|
895
|
+
{
|
|
896
|
+
tag: 'section[data-document-bibliography]',
|
|
897
|
+
getAttrs: (node)=>{
|
|
898
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
899
|
+
return {
|
|
900
|
+
id: node.dataset.bibliographyId || 'document-bibliography-1',
|
|
901
|
+
style: node.dataset.bibliographyStyle || 'apa'
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
];
|
|
906
|
+
},
|
|
907
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
908
|
+
return [
|
|
909
|
+
'section',
|
|
910
|
+
mergeAttributes(HTMLAttributes, {
|
|
911
|
+
'data-document-bibliography': 'true',
|
|
912
|
+
'data-bibliography-id': 'string' == typeof node.attrs.id ? node.attrs.id : 'document-bibliography-1',
|
|
913
|
+
'data-bibliography-style': 'string' == typeof node.attrs.style ? node.attrs.style : 'apa',
|
|
914
|
+
class: 'work-document-bibliography'
|
|
915
|
+
}),
|
|
916
|
+
0
|
|
917
|
+
];
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
function documentCitationCount(editor) {
|
|
921
|
+
let count = 0;
|
|
922
|
+
editor.state.doc.descendants((node)=>{
|
|
923
|
+
if ('documentCitation' === node.type.name) count += 1;
|
|
924
|
+
});
|
|
925
|
+
return count;
|
|
926
|
+
}
|
|
927
|
+
function insertDocumentCitationCommand({ dispatch, editor, state, tr }, source, bibliography) {
|
|
928
|
+
const citationType = editor.schema.nodes.documentCitation;
|
|
929
|
+
if (!citationType || !source.tag.trim() || work_document_citation_nodes_selectionInsideNode(state, 'documentBibliography')) return false;
|
|
930
|
+
if (!dispatch) return true;
|
|
931
|
+
const instruction = documentCitationInstruction([
|
|
932
|
+
source.tag
|
|
933
|
+
]);
|
|
934
|
+
const resolved = resolveDocumentCitation([
|
|
935
|
+
source.tag
|
|
936
|
+
], bibliography, instruction);
|
|
937
|
+
tr.replaceSelectionWith(citationType.create({
|
|
938
|
+
id: createWorkId('citation'),
|
|
939
|
+
tags: source.tag,
|
|
940
|
+
instruction,
|
|
941
|
+
display: resolved.text,
|
|
942
|
+
orphaned: resolved.orphaned
|
|
943
|
+
}), false);
|
|
944
|
+
tr.scrollIntoView();
|
|
945
|
+
return true;
|
|
946
|
+
}
|
|
947
|
+
function insertDocumentBibliographyCommand({ dispatch, editor, state, tr }, bibliography) {
|
|
948
|
+
if (!editor.schema.nodes.documentBibliography) return false;
|
|
949
|
+
const existing = documentBibliographyNodes(state.doc)[0];
|
|
950
|
+
if (!dispatch) return true;
|
|
951
|
+
if (existing) {
|
|
952
|
+
refreshDocumentCitationsInTransaction(editor, tr, bibliography);
|
|
953
|
+
tr.setSelection(NodeSelection.create(tr.doc, existing.position));
|
|
954
|
+
tr.scrollIntoView();
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
const replacement = bibliographyNode(editor, bibliography, createWorkId('bibliography'));
|
|
958
|
+
if (!replacement) return false;
|
|
959
|
+
tr.replaceSelectionWith(replacement);
|
|
960
|
+
const paragraphType = editor.schema.nodes.paragraph;
|
|
961
|
+
if (paragraphType && tr.selection.$to.parent.type === replacement.type) tr.insert(tr.selection.to, paragraphType.create());
|
|
962
|
+
tr.scrollIntoView();
|
|
963
|
+
return true;
|
|
964
|
+
}
|
|
965
|
+
function refreshDocumentCitationsCommand({ editor, tr }, content) {
|
|
966
|
+
return refreshDocumentCitationsInTransaction(editor, tr, content.bibliography);
|
|
967
|
+
}
|
|
968
|
+
function renameDocumentCitationTagCommand({ tr }, previousTag, nextTag) {
|
|
969
|
+
if (!previousTag || previousTag === nextTag) return false;
|
|
970
|
+
const document1 = tr.doc;
|
|
971
|
+
document1.descendants((node, position)=>{
|
|
972
|
+
if ('documentCitation' !== node.type.name) return;
|
|
973
|
+
const tags = documentCitationTags('string' == typeof node.attrs.tags ? node.attrs.tags : '');
|
|
974
|
+
if (!tags.includes(previousTag)) return;
|
|
975
|
+
const renamed = tags.map((tag)=>tag === previousTag ? nextTag : tag);
|
|
976
|
+
const instruction = 'string' == typeof node.attrs.instruction ? renameDocumentCitationTagInInstruction(node.attrs.instruction, previousTag, nextTag) : documentCitationInstruction(renamed);
|
|
977
|
+
tr.setNodeMarkup(position, void 0, {
|
|
978
|
+
...node.attrs,
|
|
979
|
+
tags: renamed.join(' '),
|
|
980
|
+
instruction
|
|
981
|
+
});
|
|
982
|
+
});
|
|
983
|
+
return tr.docChanged;
|
|
984
|
+
}
|
|
985
|
+
function refreshDocumentCitationsInTransaction(editor, tr, bibliography) {
|
|
986
|
+
const document1 = tr.doc;
|
|
987
|
+
const bibliographyNodes = [];
|
|
988
|
+
document1.descendants((node, position)=>{
|
|
989
|
+
if ('documentCitation' === node.type.name) {
|
|
990
|
+
const tags = documentCitationTags('string' == typeof node.attrs.tags ? node.attrs.tags : '');
|
|
991
|
+
const instruction = 'string' == typeof node.attrs.instruction ? node.attrs.instruction : '';
|
|
992
|
+
const cached = 'string' == typeof node.attrs.display ? node.attrs.display : '';
|
|
993
|
+
const resolved = resolveDocumentCitation(tags, bibliography, instruction, cached);
|
|
994
|
+
if (node.attrs.display !== resolved.text || Boolean(node.attrs.orphaned) !== resolved.orphaned) tr.setNodeMarkup(position, void 0, {
|
|
995
|
+
...node.attrs,
|
|
996
|
+
display: resolved.text,
|
|
997
|
+
orphaned: resolved.orphaned
|
|
998
|
+
});
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
if ('documentBibliography' === node.type.name) bibliographyNodes.push({
|
|
1002
|
+
node,
|
|
1003
|
+
position
|
|
1004
|
+
});
|
|
1005
|
+
});
|
|
1006
|
+
if (bibliography) for (const current of bibliographyNodes.reverse()){
|
|
1007
|
+
const id = 'string' == typeof current.node.attrs.id ? current.node.attrs.id : 'document-bibliography-1';
|
|
1008
|
+
const replacement = bibliographyNode(editor, bibliography, id);
|
|
1009
|
+
if (replacement && !current.node.eq(replacement)) tr.replaceWith(current.position, current.position + current.node.nodeSize, replacement);
|
|
1010
|
+
}
|
|
1011
|
+
return tr.docChanged;
|
|
1012
|
+
}
|
|
1013
|
+
function bibliographyNode(editor, bibliography, id) {
|
|
1014
|
+
const document1 = new DOMParser().parseFromString(renderDocumentBibliographyHtml(bibliography, id), 'text/html');
|
|
1015
|
+
const slice = model_DOMParser.fromSchema(editor.schema).parseSlice(document1.body);
|
|
1016
|
+
return slice.content.firstChild?.type.name === 'documentBibliography' ? slice.content.firstChild : null;
|
|
1017
|
+
}
|
|
1018
|
+
function documentBibliographyNodes(document1) {
|
|
1019
|
+
const result = [];
|
|
1020
|
+
document1.descendants((node, position)=>{
|
|
1021
|
+
if ('documentBibliography' === node.type.name) result.push({
|
|
1022
|
+
node,
|
|
1023
|
+
position
|
|
1024
|
+
});
|
|
1025
|
+
});
|
|
1026
|
+
return result;
|
|
1027
|
+
}
|
|
1028
|
+
function work_document_citation_nodes_selectionInsideNode(state, nodeName) {
|
|
1029
|
+
for(let depth = state.selection.$from.depth; depth > 0; depth -= 1)if (state.selection.$from.node(depth).type.name === nodeName) return true;
|
|
1030
|
+
return false;
|
|
1031
|
+
}
|
|
1032
|
+
function work_document_citation_nodes_hiddenAttribute(defaultValue) {
|
|
1033
|
+
return {
|
|
1034
|
+
default: defaultValue,
|
|
1035
|
+
rendered: false
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
const documentCommentPastePluginKey = new PluginKey('documentCommentPaste');
|
|
1039
|
+
const documentCommentDraftPluginKey = new PluginKey('documentCommentDraft');
|
|
1040
|
+
const DocumentComment = Mark.create({
|
|
1041
|
+
name: 'documentComment',
|
|
1042
|
+
priority: 1050,
|
|
1043
|
+
inclusive: false,
|
|
1044
|
+
keepOnSplit: true,
|
|
1045
|
+
excludes: '',
|
|
1046
|
+
addOptions () {
|
|
1047
|
+
return {
|
|
1048
|
+
getContent: ()=>null,
|
|
1049
|
+
onContentChange: ()=>void 0
|
|
1050
|
+
};
|
|
1051
|
+
},
|
|
1052
|
+
addAttributes () {
|
|
1053
|
+
return {
|
|
1054
|
+
id: {
|
|
1055
|
+
default: '',
|
|
1056
|
+
parseHTML: (element)=>element.getAttribute('data-comment-id') ?? '',
|
|
1057
|
+
renderHTML: (attributes)=>({
|
|
1058
|
+
'data-comment-id': attributes.id
|
|
1059
|
+
})
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
},
|
|
1063
|
+
parseHTML () {
|
|
1064
|
+
return [
|
|
1065
|
+
{
|
|
1066
|
+
tag: 'span[data-document-comment]'
|
|
1067
|
+
}
|
|
1068
|
+
];
|
|
1069
|
+
},
|
|
1070
|
+
renderHTML ({ HTMLAttributes }) {
|
|
1071
|
+
return [
|
|
1072
|
+
'span',
|
|
1073
|
+
mergeAttributes(HTMLAttributes, {
|
|
1074
|
+
'data-document-comment': 'true'
|
|
1075
|
+
}),
|
|
1076
|
+
0
|
|
1077
|
+
];
|
|
1078
|
+
},
|
|
1079
|
+
addCommands () {
|
|
1080
|
+
return {
|
|
1081
|
+
addDocumentCommentReply: (id, reply)=>({ dispatch })=>{
|
|
1082
|
+
const content = this.options.getContent();
|
|
1083
|
+
if (!content || !(content.comments ?? []).some((comment)=>comment.id === id)) return false;
|
|
1084
|
+
if (dispatch) this.options.onContentChange({
|
|
1085
|
+
...content,
|
|
1086
|
+
comments: appendDocumentCommentReply(content.comments ?? [], id, reply)
|
|
1087
|
+
});
|
|
1088
|
+
return true;
|
|
1089
|
+
},
|
|
1090
|
+
deleteDocumentComment: (id)=>({ state, dispatch })=>{
|
|
1091
|
+
const commentId = id.trim();
|
|
1092
|
+
const content = this.options.getContent();
|
|
1093
|
+
if (!commentId || !content) return false;
|
|
1094
|
+
const comments = content.comments ?? [];
|
|
1095
|
+
const hasRecord = comments.some((comment)=>comment.id === commentId);
|
|
1096
|
+
const segments = documentCommentSegments(state.doc, this.type).filter((segment)=>segment.id === commentId);
|
|
1097
|
+
if (!hasRecord && !segments.length) return false;
|
|
1098
|
+
if (!dispatch) return true;
|
|
1099
|
+
this.options.onContentChange({
|
|
1100
|
+
...content,
|
|
1101
|
+
comments: removeDocumentCommentRecord(comments, commentId)
|
|
1102
|
+
});
|
|
1103
|
+
if (segments.length) {
|
|
1104
|
+
const transaction = state.tr;
|
|
1105
|
+
for (const segment of segments)transaction.removeMark(segment.from, segment.to, this.type);
|
|
1106
|
+
if (transaction.docChanged) dispatch(transaction);
|
|
1107
|
+
}
|
|
1108
|
+
return true;
|
|
1109
|
+
},
|
|
1110
|
+
showDocumentCommentDraft: (range)=>({ state, dispatch })=>{
|
|
1111
|
+
const normalized = normalizeDocumentCommentRange(state.doc, range);
|
|
1112
|
+
if (!normalized || !canInsertDocumentCommentInState(state.doc, this.type, normalized)) return false;
|
|
1113
|
+
dispatch?.(state.tr.setMeta(documentCommentDraftPluginKey, {
|
|
1114
|
+
range: normalized
|
|
1115
|
+
}));
|
|
1116
|
+
return true;
|
|
1117
|
+
},
|
|
1118
|
+
clearDocumentCommentDraft: ()=>({ state, dispatch })=>{
|
|
1119
|
+
if (!documentCommentDraftRangeFromState(state)) return false;
|
|
1120
|
+
dispatch?.(state.tr.setMeta(documentCommentDraftPluginKey, {
|
|
1121
|
+
range: null
|
|
1122
|
+
}));
|
|
1123
|
+
return true;
|
|
1124
|
+
},
|
|
1125
|
+
insertDocumentComment: ({ id, range })=>({ state, dispatch })=>{
|
|
1126
|
+
const normalized = normalizeDocumentCommentRange(state.doc, range ?? state.selection);
|
|
1127
|
+
const commentId = id.trim();
|
|
1128
|
+
if (!normalized || !commentId || !canInsertDocumentCommentInState(state.doc, this.type, normalized)) return false;
|
|
1129
|
+
const transaction = state.tr.addMark(normalized.from, normalized.to, this.type.create({
|
|
1130
|
+
id: commentId
|
|
1131
|
+
}));
|
|
1132
|
+
if (!transaction.docChanged) return false;
|
|
1133
|
+
transaction.setMeta(documentCommentDraftPluginKey, {
|
|
1134
|
+
range: null
|
|
1135
|
+
});
|
|
1136
|
+
dispatch?.(transaction);
|
|
1137
|
+
return true;
|
|
1138
|
+
},
|
|
1139
|
+
insertDocumentCommentThread: (comment, range)=>({ state, dispatch })=>{
|
|
1140
|
+
const content = this.options.getContent();
|
|
1141
|
+
const normalized = normalizeDocumentCommentRange(state.doc, range ?? state.selection);
|
|
1142
|
+
const commentId = comment.id.trim();
|
|
1143
|
+
if (!content || !normalized || !commentId || (content.comments ?? []).some((candidate)=>candidate.id === commentId) || !canInsertDocumentCommentInState(state.doc, this.type, normalized)) return false;
|
|
1144
|
+
if (!dispatch) return true;
|
|
1145
|
+
this.options.onContentChange({
|
|
1146
|
+
...content,
|
|
1147
|
+
comments: [
|
|
1148
|
+
...content.comments ?? [],
|
|
1149
|
+
comment
|
|
1150
|
+
]
|
|
1151
|
+
});
|
|
1152
|
+
const transaction = state.tr.addMark(normalized.from, normalized.to, this.type.create({
|
|
1153
|
+
id: commentId
|
|
1154
|
+
}));
|
|
1155
|
+
transaction.setMeta(documentCommentDraftPluginKey, {
|
|
1156
|
+
range: null
|
|
1157
|
+
});
|
|
1158
|
+
dispatch(transaction);
|
|
1159
|
+
return true;
|
|
1160
|
+
},
|
|
1161
|
+
removeDocumentComment: (id)=>({ state, dispatch })=>{
|
|
1162
|
+
const commentId = id.trim();
|
|
1163
|
+
if (!commentId) return false;
|
|
1164
|
+
const segments = documentCommentSegments(state.doc, this.type).filter((segment)=>segment.id === commentId);
|
|
1165
|
+
if (!segments.length) return false;
|
|
1166
|
+
const transaction = state.tr;
|
|
1167
|
+
for (const segment of segments)transaction.removeMark(segment.from, segment.to, this.type);
|
|
1168
|
+
if (!transaction.docChanged) return false;
|
|
1169
|
+
dispatch?.(transaction);
|
|
1170
|
+
return true;
|
|
1171
|
+
},
|
|
1172
|
+
toggleDocumentCommentResolved: (id)=>({ dispatch })=>{
|
|
1173
|
+
const content = this.options.getContent();
|
|
1174
|
+
if (!content || !(content.comments ?? []).some((comment)=>comment.id === id)) return false;
|
|
1175
|
+
if (dispatch) this.options.onContentChange({
|
|
1176
|
+
...content,
|
|
1177
|
+
comments: toggleDocumentCommentResolved(content.comments ?? [], id)
|
|
1178
|
+
});
|
|
1179
|
+
return true;
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
},
|
|
1183
|
+
addProseMirrorPlugins () {
|
|
1184
|
+
const type = this.type;
|
|
1185
|
+
return [
|
|
1186
|
+
new Plugin({
|
|
1187
|
+
key: documentCommentPastePluginKey,
|
|
1188
|
+
props: {
|
|
1189
|
+
transformPasted: (slice)=>stripDocumentCommentsFromSlice(slice, type)
|
|
1190
|
+
}
|
|
1191
|
+
}),
|
|
1192
|
+
new Plugin({
|
|
1193
|
+
key: documentCommentDraftPluginKey,
|
|
1194
|
+
state: {
|
|
1195
|
+
init: ()=>DecorationSet.empty,
|
|
1196
|
+
apply: (transaction, current)=>{
|
|
1197
|
+
const mapped = current.map(transaction.mapping, transaction.doc);
|
|
1198
|
+
const meta = transaction.getMeta(documentCommentDraftPluginKey);
|
|
1199
|
+
if (!meta) return mapped;
|
|
1200
|
+
const range = normalizeDocumentCommentRange(transaction.doc, meta.range);
|
|
1201
|
+
if (!range) return DecorationSet.empty;
|
|
1202
|
+
return DecorationSet.create(transaction.doc, [
|
|
1203
|
+
Decoration.inline(range.from, range.to, {
|
|
1204
|
+
class: 'work-document-comment-draft',
|
|
1205
|
+
'data-document-comment-draft': 'true'
|
|
1206
|
+
}, {
|
|
1207
|
+
inclusiveStart: false,
|
|
1208
|
+
inclusiveEnd: false
|
|
1209
|
+
})
|
|
1210
|
+
]);
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
props: {
|
|
1214
|
+
decorations: (state)=>documentCommentDraftPluginKey.getState(state) ?? DecorationSet.empty
|
|
1215
|
+
}
|
|
1216
|
+
})
|
|
1217
|
+
];
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
function canInsertDocumentComment(editor, range = editor.state.selection) {
|
|
1221
|
+
const type = editor.schema.marks.documentComment;
|
|
1222
|
+
return canInsertDocumentCommentInState(editor.state.doc, type, range);
|
|
1223
|
+
}
|
|
1224
|
+
function documentCommentDraftRange(editor) {
|
|
1225
|
+
return documentCommentDraftRangeFromState(editor.state);
|
|
1226
|
+
}
|
|
1227
|
+
function documentCommentDraftRangeFromState(state) {
|
|
1228
|
+
const decorations = documentCommentDraftPluginKey.getState(state)?.find();
|
|
1229
|
+
if (!decorations?.length) return null;
|
|
1230
|
+
return {
|
|
1231
|
+
from: Math.min(...decorations.map((decoration)=>decoration.from)),
|
|
1232
|
+
to: Math.max(...decorations.map((decoration)=>decoration.to))
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
function collectDocumentCommentAnchors(document1) {
|
|
1236
|
+
const anchors = new Map();
|
|
1237
|
+
document1.descendants((node, position)=>{
|
|
1238
|
+
if (!node.isText || !node.text) return;
|
|
1239
|
+
const mark = documentCommentMark(node.marks);
|
|
1240
|
+
const id = mark ? work_document_comments_stringAttribute(mark.attrs.id).trim() : '';
|
|
1241
|
+
if (!id) return;
|
|
1242
|
+
const current = anchors.get(id);
|
|
1243
|
+
if (current) {
|
|
1244
|
+
current.from = Math.min(current.from, position);
|
|
1245
|
+
current.to = Math.max(current.to, position + node.nodeSize);
|
|
1246
|
+
current.anchorText += node.text;
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
anchors.set(id, {
|
|
1250
|
+
id,
|
|
1251
|
+
from: position,
|
|
1252
|
+
to: position + node.nodeSize,
|
|
1253
|
+
anchorText: node.text
|
|
1254
|
+
});
|
|
1255
|
+
});
|
|
1256
|
+
return Array.from(anchors.values()).sort((left, right)=>left.from - right.from);
|
|
1257
|
+
}
|
|
1258
|
+
function documentCommentViews(comments, anchors) {
|
|
1259
|
+
const byId = new Map(comments.map((comment)=>[
|
|
1260
|
+
comment.id,
|
|
1261
|
+
normalizeDocumentComment(comment)
|
|
1262
|
+
]));
|
|
1263
|
+
return anchors.map((anchor)=>({
|
|
1264
|
+
...byId.get(anchor.id) ?? {
|
|
1265
|
+
id: anchor.id,
|
|
1266
|
+
author: '未知审阅者',
|
|
1267
|
+
date: '',
|
|
1268
|
+
text: '此批注的内容不可用。',
|
|
1269
|
+
resolved: false
|
|
1270
|
+
},
|
|
1271
|
+
...anchor
|
|
1272
|
+
}));
|
|
1273
|
+
}
|
|
1274
|
+
function retainAnchoredDocumentComments(comments, anchors) {
|
|
1275
|
+
const ids = new Set(anchors.map((anchor)=>anchor.id));
|
|
1276
|
+
return comments.filter((comment)=>ids.has(comment.id)).map(normalizeDocumentComment);
|
|
1277
|
+
}
|
|
1278
|
+
function appendDocumentCommentReply(comments, id, reply) {
|
|
1279
|
+
return comments.map((comment)=>comment.id === id ? {
|
|
1280
|
+
...comment,
|
|
1281
|
+
replies: [
|
|
1282
|
+
...comment.replies ?? [],
|
|
1283
|
+
reply
|
|
1284
|
+
]
|
|
1285
|
+
} : comment);
|
|
1286
|
+
}
|
|
1287
|
+
function toggleDocumentCommentResolved(comments, id) {
|
|
1288
|
+
return comments.map((comment)=>comment.id === id ? {
|
|
1289
|
+
...comment,
|
|
1290
|
+
resolved: !comment.resolved
|
|
1291
|
+
} : comment);
|
|
1292
|
+
}
|
|
1293
|
+
function removeDocumentCommentRecord(comments, id) {
|
|
1294
|
+
return comments.filter((comment)=>comment.id !== id);
|
|
1295
|
+
}
|
|
1296
|
+
function stripDocumentCommentsFromSlice(slice, type) {
|
|
1297
|
+
return new Slice(stripDocumentCommentMarks(slice.content, type), slice.openStart, slice.openEnd);
|
|
1298
|
+
}
|
|
1299
|
+
function selectionContainsDocumentComment(document1, from, to) {
|
|
1300
|
+
let found = false;
|
|
1301
|
+
document1.nodesBetween(from, to, (node)=>{
|
|
1302
|
+
if (node.isText && documentCommentMark(node.marks)) found = true;
|
|
1303
|
+
return !found;
|
|
1304
|
+
});
|
|
1305
|
+
return found;
|
|
1306
|
+
}
|
|
1307
|
+
function canInsertDocumentCommentInState(document1, type, range) {
|
|
1308
|
+
const normalized = normalizeDocumentCommentRange(document1, range);
|
|
1309
|
+
if (!type || !normalized) return false;
|
|
1310
|
+
const selectedText = document1.textBetween(normalized.from, normalized.to, '\n');
|
|
1311
|
+
return Boolean(selectedText.trim()) && !selectionContainsDocumentComment(document1, normalized.from, normalized.to);
|
|
1312
|
+
}
|
|
1313
|
+
function normalizeDocumentCommentRange(document1, range) {
|
|
1314
|
+
if (!range) return null;
|
|
1315
|
+
const from = Math.max(0, Math.min(document1.content.size, range.from));
|
|
1316
|
+
const to = Math.max(0, Math.min(document1.content.size, range.to));
|
|
1317
|
+
return from < to ? {
|
|
1318
|
+
from,
|
|
1319
|
+
to
|
|
1320
|
+
} : null;
|
|
1321
|
+
}
|
|
1322
|
+
function documentCommentSegments(document1, type) {
|
|
1323
|
+
const segments = [];
|
|
1324
|
+
document1.descendants((node, position)=>{
|
|
1325
|
+
if (!node.isText) return;
|
|
1326
|
+
const mark = node.marks.find((candidate)=>candidate.type === type);
|
|
1327
|
+
const id = mark ? work_document_comments_stringAttribute(mark.attrs.id).trim() : '';
|
|
1328
|
+
if (id) segments.push({
|
|
1329
|
+
id,
|
|
1330
|
+
from: position,
|
|
1331
|
+
to: position + node.nodeSize
|
|
1332
|
+
});
|
|
1333
|
+
});
|
|
1334
|
+
return segments;
|
|
1335
|
+
}
|
|
1336
|
+
function stripDocumentCommentMarks(fragment, type) {
|
|
1337
|
+
const nodes = [];
|
|
1338
|
+
fragment.forEach((node)=>{
|
|
1339
|
+
const content = node.content.size ? stripDocumentCommentMarks(node.content, type) : node.content;
|
|
1340
|
+
const copy = node.content.size ? node.copy(content) : node;
|
|
1341
|
+
nodes.push(copy.mark(copy.marks.filter((mark)=>mark.type !== type)));
|
|
1342
|
+
});
|
|
1343
|
+
return Fragment.fromArray(nodes);
|
|
1344
|
+
}
|
|
1345
|
+
function documentCommentMark(marks) {
|
|
1346
|
+
return marks.find((mark)=>'documentComment' === mark.type.name);
|
|
1347
|
+
}
|
|
1348
|
+
function normalizeDocumentComment(comment) {
|
|
1349
|
+
return {
|
|
1350
|
+
id: comment.id,
|
|
1351
|
+
author: comment.author || '未知审阅者',
|
|
1352
|
+
date: comment.date || '',
|
|
1353
|
+
text: comment.text || '(空批注)',
|
|
1354
|
+
resolved: Boolean(comment.resolved),
|
|
1355
|
+
replies: comment.replies?.map((reply)=>({
|
|
1356
|
+
id: reply.id,
|
|
1357
|
+
author: reply.author || '未知审阅者',
|
|
1358
|
+
date: reply.date || '',
|
|
1359
|
+
text: reply.text || '(空回复)'
|
|
1360
|
+
}))
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
function work_document_comments_stringAttribute(value) {
|
|
1364
|
+
return 'string' == typeof value ? value : '';
|
|
1365
|
+
}
|
|
1366
|
+
function documentPageDescriptors(content) {
|
|
1367
|
+
const noteCollection = collectDocumentNotes(content.html);
|
|
1368
|
+
const canonicalContent = {
|
|
1369
|
+
...content,
|
|
1370
|
+
html: noteCollection.html
|
|
1371
|
+
};
|
|
1372
|
+
const sections = documentSections(canonicalContent);
|
|
1373
|
+
const pages = [];
|
|
1374
|
+
let nextPageNumber = sections[0]?.layout.pageNumberStart ?? 1;
|
|
1375
|
+
let currentPage = null;
|
|
1376
|
+
sections.forEach((section, sectionIndex)=>{
|
|
1377
|
+
const parts = safeSectionPages(section.html);
|
|
1378
|
+
const previousBreak = sectionIndex > 0 ? sections[sectionIndex - 1].layout.breakAfter : null;
|
|
1379
|
+
const restartsNumbering = void 0 !== section.layout.pageNumberStart;
|
|
1380
|
+
const continuesCurrentPage = sectionIndex > 0 && !restartsNumbering && ('continuous' === previousBreak || 'nextColumn' === previousBreak) && null !== currentPage && samePhysicalPageLayout(currentPage.layout, section.layout);
|
|
1381
|
+
let sectionPage = continuesCurrentPage ? 1 : 0;
|
|
1382
|
+
if (!continuesCurrentPage) {
|
|
1383
|
+
if ('evenPage' === previousBreak || 'oddPage' === previousBreak) {
|
|
1384
|
+
const desiredParity = 'evenPage' === previousBreak ? 0 : 1;
|
|
1385
|
+
const nextPhysicalPage = pages.length + 1;
|
|
1386
|
+
if (nextPhysicalPage % 2 !== desiredParity) {
|
|
1387
|
+
pages.push(createPage(section.layout, nextPageNumber, pages.length + 1, 0, true));
|
|
1388
|
+
nextPageNumber += 1;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
if (restartsNumbering) nextPageNumber = section.layout.pageNumberStart ?? nextPageNumber;
|
|
1392
|
+
sectionPage = 1;
|
|
1393
|
+
currentPage = createPage(section.layout, nextPageNumber, pages.length + 1, sectionPage, false);
|
|
1394
|
+
pages.push(currentPage);
|
|
1395
|
+
nextPageNumber += 1;
|
|
1396
|
+
}
|
|
1397
|
+
parts.forEach((html, partIndex)=>{
|
|
1398
|
+
if (partIndex > 0) {
|
|
1399
|
+
sectionPage += 1;
|
|
1400
|
+
currentPage = createPage(section.layout, nextPageNumber, pages.length + 1, sectionPage, false);
|
|
1401
|
+
pages.push(currentPage);
|
|
1402
|
+
nextPageNumber += 1;
|
|
1403
|
+
}
|
|
1404
|
+
currentPage?.segments.push({
|
|
1405
|
+
sectionId: section.id,
|
|
1406
|
+
html,
|
|
1407
|
+
columns: section.layout.columns
|
|
1408
|
+
});
|
|
1409
|
+
});
|
|
1410
|
+
});
|
|
1411
|
+
const result = pages.length ? pages : [
|
|
1412
|
+
createPage(documentSections(content)[0]?.layout, content.pageNumberStart ?? 1, 1, 1, false)
|
|
1413
|
+
];
|
|
1414
|
+
resolveDocumentPageFields(result, sections);
|
|
1415
|
+
attachDocumentNotes(result, noteCollection.notes);
|
|
1416
|
+
return result;
|
|
1417
|
+
}
|
|
1418
|
+
function resolveDocumentPageFields(pages, sections) {
|
|
1419
|
+
const sectionNumbers = new Map(sections.map((section, index)=>[
|
|
1420
|
+
section.id,
|
|
1421
|
+
index + 1
|
|
1422
|
+
]));
|
|
1423
|
+
const sectionPages = new Map();
|
|
1424
|
+
for (const page of pages)for (const sectionId of new Set(page.segments.map((segment)=>segment.sectionId)))sectionPages.set(sectionId, (sectionPages.get(sectionId) ?? 0) + 1);
|
|
1425
|
+
const now = new Date();
|
|
1426
|
+
for (const page of pages)for (const segment of page.segments)segment.html = resolveDocumentFieldsHtml(segment.html, {
|
|
1427
|
+
pageNumber: page.pageNumber,
|
|
1428
|
+
totalPages: pages.length,
|
|
1429
|
+
sectionNumber: sectionNumbers.get(segment.sectionId) ?? 1,
|
|
1430
|
+
sectionPages: sectionPages.get(segment.sectionId) ?? 1,
|
|
1431
|
+
now
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
function samePhysicalPageLayout(current, next) {
|
|
1435
|
+
return current.pageSize === next.pageSize && current.orientation === next.orientation && current.margins.top === next.margins.top && current.margins.right === next.margins.right && current.margins.bottom === next.margins.bottom && current.margins.left === next.margins.left;
|
|
1436
|
+
}
|
|
1437
|
+
function createPage(layout, pageNumber, physicalPage, sectionPage, blank) {
|
|
1438
|
+
const effectiveLayout = layout ?? {
|
|
1439
|
+
pageSize: 'a4',
|
|
1440
|
+
orientation: 'portrait',
|
|
1441
|
+
margins: {
|
|
1442
|
+
top: 25,
|
|
1443
|
+
right: 23,
|
|
1444
|
+
bottom: 25,
|
|
1445
|
+
left: 23
|
|
1446
|
+
},
|
|
1447
|
+
columns: {
|
|
1448
|
+
count: 1,
|
|
1449
|
+
spacing: 12,
|
|
1450
|
+
separator: false
|
|
1451
|
+
},
|
|
1452
|
+
breakAfter: 'nextPage'
|
|
1453
|
+
};
|
|
1454
|
+
return {
|
|
1455
|
+
key: `document-page-${physicalPage}`,
|
|
1456
|
+
layout: effectiveLayout,
|
|
1457
|
+
segments: [],
|
|
1458
|
+
pageNumber,
|
|
1459
|
+
physicalPage,
|
|
1460
|
+
sectionPage,
|
|
1461
|
+
blank,
|
|
1462
|
+
footnotes: [],
|
|
1463
|
+
endnotes: []
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
function safeSectionPages(source) {
|
|
1467
|
+
const document1 = new DOMParser().parseFromString(removeDocumentNoteDefinitions(source), 'text/html');
|
|
1468
|
+
sanitizeDocument(document1);
|
|
1469
|
+
const pages = [
|
|
1470
|
+
document1.createElement('div')
|
|
1471
|
+
];
|
|
1472
|
+
for (const node of Array.from(document1.body.childNodes)){
|
|
1473
|
+
if (node instanceof Element && node.hasAttribute('data-page-break')) {
|
|
1474
|
+
pages.push(document1.createElement('div'));
|
|
1475
|
+
continue;
|
|
1476
|
+
}
|
|
1477
|
+
pages.at(-1)?.append(node.cloneNode(true));
|
|
1478
|
+
}
|
|
1479
|
+
return pages.map((page)=>page.innerHTML);
|
|
1480
|
+
}
|
|
1481
|
+
function sanitizeDocument(document1) {
|
|
1482
|
+
for (const element of Array.from(document1.body.querySelectorAll("script, iframe, object, embed, link, meta")))element.remove();
|
|
1483
|
+
for (const element of Array.from(document1.body.querySelectorAll('*'))){
|
|
1484
|
+
for (const attribute of Array.from(element.attributes))if (attribute.name.toLowerCase().startsWith('on')) element.removeAttribute(attribute.name);
|
|
1485
|
+
if (element instanceof HTMLAnchorElement && /^(?:javascript|vbscript|data):/i.test(element.getAttribute('href')?.trim() ?? '')) element.removeAttribute('href');
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
function attachDocumentNotes(pages, notes) {
|
|
1489
|
+
const safeNotes = notes.map((note)=>({
|
|
1490
|
+
...note,
|
|
1491
|
+
html: safeNoteHtml(note.html)
|
|
1492
|
+
}));
|
|
1493
|
+
const byKey = new Map(safeNotes.map((note)=>[
|
|
1494
|
+
documentNoteKey(note.kind, note.id),
|
|
1495
|
+
note
|
|
1496
|
+
]));
|
|
1497
|
+
for (const page of pages){
|
|
1498
|
+
const keys = new Set(page.segments.flatMap((segment)=>documentNoteReferenceKeys(segment.html)));
|
|
1499
|
+
page.footnotes = Array.from(keys).map((key)=>byKey.get(key)).filter((note)=>note?.kind === 'footnote');
|
|
1500
|
+
}
|
|
1501
|
+
const lastContentPage = [
|
|
1502
|
+
...pages
|
|
1503
|
+
].reverse().find((page)=>!page.blank);
|
|
1504
|
+
if (lastContentPage) lastContentPage.endnotes = safeNotes.filter((note)=>'endnote' === note.kind);
|
|
1505
|
+
}
|
|
1506
|
+
function safeNoteHtml(source) {
|
|
1507
|
+
const document1 = new DOMParser().parseFromString(source, 'text/html');
|
|
1508
|
+
sanitizeDocument(document1);
|
|
1509
|
+
return document1.body.innerHTML;
|
|
1510
|
+
}
|
|
1511
|
+
const DocumentField = Node.create({
|
|
1512
|
+
name: 'documentField',
|
|
1513
|
+
inline: true,
|
|
1514
|
+
group: 'inline',
|
|
1515
|
+
atom: true,
|
|
1516
|
+
selectable: true,
|
|
1517
|
+
addCommands () {
|
|
1518
|
+
return {
|
|
1519
|
+
insertDocumentField: (kind)=>(props)=>insertDocumentFieldCommand(props, kind),
|
|
1520
|
+
refreshDocumentFields: (content)=>(props)=>refreshDocumentFieldsCommand(props, content)
|
|
1521
|
+
};
|
|
1522
|
+
},
|
|
1523
|
+
addAttributes () {
|
|
1524
|
+
return {
|
|
1525
|
+
id: work_document_field_node_hiddenAttribute(''),
|
|
1526
|
+
kind: work_document_field_node_hiddenAttribute('page'),
|
|
1527
|
+
instruction: work_document_field_node_hiddenAttribute('PAGE'),
|
|
1528
|
+
display: work_document_field_node_hiddenAttribute('1')
|
|
1529
|
+
};
|
|
1530
|
+
},
|
|
1531
|
+
parseHTML () {
|
|
1532
|
+
return [
|
|
1533
|
+
{
|
|
1534
|
+
tag: 'span[data-document-field]',
|
|
1535
|
+
getAttrs: (node)=>{
|
|
1536
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
1537
|
+
const instruction = node.dataset.fieldInstruction?.trim() ?? '';
|
|
1538
|
+
const kind = documentFieldKind(node.dataset.fieldKind) ?? docxDocumentFieldKind(instruction) ?? 'page';
|
|
1539
|
+
return {
|
|
1540
|
+
id: node.dataset.fieldId ?? '',
|
|
1541
|
+
kind,
|
|
1542
|
+
instruction: instruction || documentFieldInstruction(kind),
|
|
1543
|
+
display: node.dataset.fieldDisplay?.trim() || node.textContent?.trim() || documentFieldLabel(kind)
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
];
|
|
1548
|
+
},
|
|
1549
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
1550
|
+
const instruction = 'string' == typeof node.attrs.instruction ? node.attrs.instruction.trim() : '';
|
|
1551
|
+
const kind = documentFieldKind(node.attrs.kind) ?? docxDocumentFieldKind(instruction) ?? 'page';
|
|
1552
|
+
const display = 'string' == typeof node.attrs.display && node.attrs.display.trim() ? node.attrs.display.trim() : documentFieldLabel(kind);
|
|
1553
|
+
return [
|
|
1554
|
+
'span',
|
|
1555
|
+
mergeAttributes(HTMLAttributes, {
|
|
1556
|
+
'data-document-field': 'true',
|
|
1557
|
+
'data-field-id': 'string' == typeof node.attrs.id ? node.attrs.id : '',
|
|
1558
|
+
'data-field-kind': kind,
|
|
1559
|
+
'data-field-instruction': instruction || documentFieldInstruction(kind),
|
|
1560
|
+
'data-field-display': display,
|
|
1561
|
+
class: 'work-document-field',
|
|
1562
|
+
title: documentFieldLabel(kind)
|
|
1563
|
+
}),
|
|
1564
|
+
display
|
|
1565
|
+
];
|
|
1566
|
+
},
|
|
1567
|
+
renderText ({ node }) {
|
|
1568
|
+
const kind = documentFieldKind(node.attrs.kind) ?? 'page';
|
|
1569
|
+
return 'string' == typeof node.attrs.display && node.attrs.display.trim() ? node.attrs.display.trim() : documentFieldLabel(kind);
|
|
1570
|
+
}
|
|
1571
|
+
});
|
|
1572
|
+
function insertDocumentFieldCommand({ dispatch, editor, state, tr }, kind) {
|
|
1573
|
+
const fieldType = editor.schema.nodes.documentField;
|
|
1574
|
+
if (!fieldType) return false;
|
|
1575
|
+
if (!dispatch) return true;
|
|
1576
|
+
const instruction = documentFieldInstruction(kind);
|
|
1577
|
+
tr.replaceSelectionWith(fieldType.create({
|
|
1578
|
+
id: createWorkId('field'),
|
|
1579
|
+
kind,
|
|
1580
|
+
instruction,
|
|
1581
|
+
display: documentFieldDisplay(kind, fallbackContext(state), instruction)
|
|
1582
|
+
}), false);
|
|
1583
|
+
tr.scrollIntoView();
|
|
1584
|
+
return true;
|
|
1585
|
+
}
|
|
1586
|
+
function refreshDocumentFieldsCommand({ editor, state, tr }, content) {
|
|
1587
|
+
const canonical = syncDocumentContentFromHtml(content, editor.getHTML());
|
|
1588
|
+
const displays = documentPageDescriptors(canonical).flatMap((page)=>page.segments.flatMap((segment)=>{
|
|
1589
|
+
const document1 = new DOMParser().parseFromString(segment.html, 'text/html');
|
|
1590
|
+
return Array.from(document1.body.querySelectorAll('[data-document-field]')).map((element)=>element.dataset.fieldDisplay?.trim() || element.textContent?.trim() || '');
|
|
1591
|
+
}));
|
|
1592
|
+
let fieldIndex = 0;
|
|
1593
|
+
state.doc.descendants((node, position)=>{
|
|
1594
|
+
if ('documentField' !== node.type.name) return;
|
|
1595
|
+
const display = displays[fieldIndex];
|
|
1596
|
+
fieldIndex += 1;
|
|
1597
|
+
if (!display || node.attrs.display === display) return;
|
|
1598
|
+
tr.setNodeMarkup(position, void 0, {
|
|
1599
|
+
...node.attrs,
|
|
1600
|
+
display
|
|
1601
|
+
});
|
|
1602
|
+
});
|
|
1603
|
+
return tr.docChanged;
|
|
1604
|
+
}
|
|
1605
|
+
function fallbackContext(state) {
|
|
1606
|
+
let totalPages = 0;
|
|
1607
|
+
let sectionNumber = 1;
|
|
1608
|
+
let sectionPages = 1;
|
|
1609
|
+
let pageNumber = 1;
|
|
1610
|
+
let pagesBeforeSelection = 0;
|
|
1611
|
+
let foundSelection = false;
|
|
1612
|
+
state.doc.forEach((section, offset, index)=>{
|
|
1613
|
+
if ('documentSection' !== section.type.name) return;
|
|
1614
|
+
const pages = countPageBreaks(section) + 1;
|
|
1615
|
+
totalPages += pages;
|
|
1616
|
+
if (!foundSelection && state.selection.from <= offset + section.nodeSize) {
|
|
1617
|
+
sectionNumber = index + 1;
|
|
1618
|
+
sectionPages = pages;
|
|
1619
|
+
pageNumber = pagesBeforeSelection + 1 + countPageBreaksBefore(section, state.selection.from - offset - 1);
|
|
1620
|
+
foundSelection = true;
|
|
1621
|
+
}
|
|
1622
|
+
if (!foundSelection) pagesBeforeSelection += pages;
|
|
1623
|
+
});
|
|
1624
|
+
return {
|
|
1625
|
+
pageNumber,
|
|
1626
|
+
totalPages: Math.max(1, totalPages),
|
|
1627
|
+
sectionNumber,
|
|
1628
|
+
sectionPages
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
function countPageBreaks(node) {
|
|
1632
|
+
let count = 0;
|
|
1633
|
+
node.descendants((child)=>{
|
|
1634
|
+
if ('pageBreak' === child.type.name) count += 1;
|
|
1635
|
+
});
|
|
1636
|
+
return count;
|
|
1637
|
+
}
|
|
1638
|
+
function countPageBreaksBefore(node, position) {
|
|
1639
|
+
let count = 0;
|
|
1640
|
+
node.descendants((child, offset)=>{
|
|
1641
|
+
if (offset >= position) return false;
|
|
1642
|
+
if ('pageBreak' === child.type.name) count += 1;
|
|
1643
|
+
return true;
|
|
1644
|
+
});
|
|
1645
|
+
return count;
|
|
1646
|
+
}
|
|
1647
|
+
function work_document_field_node_hiddenAttribute(defaultValue) {
|
|
1648
|
+
return {
|
|
1649
|
+
default: defaultValue,
|
|
1650
|
+
rendered: false
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
const MAX_DOCUMENT_NUMBERING_START = 2147483647;
|
|
1654
|
+
const DocumentBulletList = BulletList.extend({
|
|
1655
|
+
addAttributes () {
|
|
1656
|
+
return {
|
|
1657
|
+
bulletStyle: {
|
|
1658
|
+
default: 'disc',
|
|
1659
|
+
parseHTML: (element)=>parsedBulletStyle(element) ?? 'disc',
|
|
1660
|
+
renderHTML: (attributes)=>{
|
|
1661
|
+
const style = normalizeBulletStyle(attributes.bulletStyle) ?? 'disc';
|
|
1662
|
+
return 'disc' === style ? {} : {
|
|
1663
|
+
'data-office-bullet-style': style,
|
|
1664
|
+
style: `list-style-type: ${style}`
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
});
|
|
1671
|
+
const DocumentOrderedList = OrderedList;
|
|
1672
|
+
const DocumentListCommands = Extension.create({
|
|
1673
|
+
name: 'documentListCommands',
|
|
1674
|
+
addCommands () {
|
|
1675
|
+
return {
|
|
1676
|
+
applyDocumentBulletList: (style)=>(props)=>applyDocumentBulletList(props, style),
|
|
1677
|
+
applyDocumentOrderedList: (style)=>(props)=>applyDocumentOrderedList(props, style),
|
|
1678
|
+
clearDocumentList: ()=>(props)=>clearDocumentList(props),
|
|
1679
|
+
continueDocumentNumbering: ()=>(props)=>continueDocumentNumbering(props),
|
|
1680
|
+
restartDocumentNumbering: ()=>(props)=>setDocumentNumberingStart(props, 1),
|
|
1681
|
+
setDocumentNumberingStart: (start)=>(props)=>setDocumentNumberingStart(props, start)
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1685
|
+
function documentBulletListStyle(editor) {
|
|
1686
|
+
const active = activeList(editor.state, 'bulletList');
|
|
1687
|
+
if (!active) return null;
|
|
1688
|
+
return normalizeBulletStyle(active.node.attrs.bulletStyle) ?? 'disc';
|
|
1689
|
+
}
|
|
1690
|
+
function documentOrderedListState(editor) {
|
|
1691
|
+
const active = activeList(editor.state, 'orderedList');
|
|
1692
|
+
if (!active) return null;
|
|
1693
|
+
return {
|
|
1694
|
+
start: normalizedNumberingStart(active.node.attrs.start),
|
|
1695
|
+
style: orderedListStyle(active.node.attrs.type)
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
function applyDocumentBulletList(props, style) {
|
|
1699
|
+
const normalized = normalizeBulletStyle(style);
|
|
1700
|
+
if (!normalized) return false;
|
|
1701
|
+
const current = activeList(props.state, 'bulletList');
|
|
1702
|
+
if (current) return updateListAttributes(props, current, {
|
|
1703
|
+
bulletStyle: normalized
|
|
1704
|
+
});
|
|
1705
|
+
return props.chain().toggleBulletList().updateAttributes('bulletList', {
|
|
1706
|
+
bulletStyle: normalized
|
|
1707
|
+
}).run();
|
|
1708
|
+
}
|
|
1709
|
+
function applyDocumentOrderedList(props, style) {
|
|
1710
|
+
const type = orderedListType(style);
|
|
1711
|
+
if (void 0 === type) return false;
|
|
1712
|
+
const current = activeList(props.state, 'orderedList');
|
|
1713
|
+
if (current) return updateListAttributes(props, current, {
|
|
1714
|
+
type
|
|
1715
|
+
});
|
|
1716
|
+
return props.chain().toggleOrderedList().updateAttributes('orderedList', {
|
|
1717
|
+
start: 1,
|
|
1718
|
+
type
|
|
1719
|
+
}).run();
|
|
1720
|
+
}
|
|
1721
|
+
function clearDocumentList(props) {
|
|
1722
|
+
if (activeList(props.state, 'bulletList')) return props.commands.toggleBulletList();
|
|
1723
|
+
if (activeList(props.state, 'orderedList')) return props.commands.toggleOrderedList();
|
|
1724
|
+
return false;
|
|
1725
|
+
}
|
|
1726
|
+
function setDocumentNumberingStart(props, start) {
|
|
1727
|
+
if (!validNumberingStart(start)) return false;
|
|
1728
|
+
const current = activeList(props.state, 'orderedList');
|
|
1729
|
+
if (!current) return false;
|
|
1730
|
+
return updateListAttributes(props, current, {
|
|
1731
|
+
start
|
|
1732
|
+
});
|
|
1733
|
+
}
|
|
1734
|
+
function continueDocumentNumbering(props) {
|
|
1735
|
+
const current = activeList(props.state, 'orderedList');
|
|
1736
|
+
if (!current) return false;
|
|
1737
|
+
const previous = precedingOrderedList(props.state.doc, current);
|
|
1738
|
+
if (!previous) return false;
|
|
1739
|
+
const start = Math.min(MAX_DOCUMENT_NUMBERING_START, normalizedNumberingStart(previous.node.attrs.start) + previous.node.childCount);
|
|
1740
|
+
return updateListAttributes(props, current, {
|
|
1741
|
+
start,
|
|
1742
|
+
type: normalizedOrderedListType(previous.node.attrs.type)
|
|
1743
|
+
});
|
|
1744
|
+
}
|
|
1745
|
+
function updateListAttributes({ dispatch, state }, list, attributes) {
|
|
1746
|
+
const next = {
|
|
1747
|
+
...list.node.attrs,
|
|
1748
|
+
...attributes
|
|
1749
|
+
};
|
|
1750
|
+
if (Object.entries(attributes).every(([key, value])=>list.node.attrs[key] === value)) return true;
|
|
1751
|
+
dispatch?.(state.tr.setNodeMarkup(list.position, void 0, next, list.node.marks).scrollIntoView());
|
|
1752
|
+
return true;
|
|
1753
|
+
}
|
|
1754
|
+
function activeList(state, nodeName) {
|
|
1755
|
+
const position = state.selection.$from;
|
|
1756
|
+
for(let depth = position.depth; depth > 0; depth -= 1){
|
|
1757
|
+
const node = position.node(depth);
|
|
1758
|
+
if (node.type.name === nodeName) return {
|
|
1759
|
+
depth,
|
|
1760
|
+
node,
|
|
1761
|
+
position: position.before(depth)
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
return null;
|
|
1765
|
+
}
|
|
1766
|
+
function precedingOrderedList(document1, current) {
|
|
1767
|
+
let previous = null;
|
|
1768
|
+
document1.descendants((node, position)=>{
|
|
1769
|
+
if (position >= current.position) return false;
|
|
1770
|
+
if ('orderedList' !== node.type.name) return true;
|
|
1771
|
+
const parentDepth = document1.resolve(position).depth;
|
|
1772
|
+
if (parentDepth === current.depth - 1) previous = {
|
|
1773
|
+
depth: parentDepth + 1,
|
|
1774
|
+
node,
|
|
1775
|
+
position
|
|
1776
|
+
};
|
|
1777
|
+
return true;
|
|
1778
|
+
});
|
|
1779
|
+
return previous;
|
|
1780
|
+
}
|
|
1781
|
+
function parsedBulletStyle(element) {
|
|
1782
|
+
const direct = element.dataset.officeBulletStyle || element.style.listStyleType;
|
|
1783
|
+
const fromList = normalizeBulletStyle(direct);
|
|
1784
|
+
if (fromList) return fromList;
|
|
1785
|
+
return normalizeBulletStyle(element.querySelector(':scope > li')?.style.listStyleType);
|
|
1786
|
+
}
|
|
1787
|
+
function normalizeBulletStyle(value) {
|
|
1788
|
+
return 'disc' === value || 'circle' === value || 'square' === value ? value : null;
|
|
1789
|
+
}
|
|
1790
|
+
function orderedListType(style) {
|
|
1791
|
+
if ('decimal' === style) return null;
|
|
1792
|
+
if ('lower-alpha' === style) return 'a';
|
|
1793
|
+
if ('upper-alpha' === style) return 'A';
|
|
1794
|
+
if ('lower-roman' === style) return 'i';
|
|
1795
|
+
if ('upper-roman' === style) return 'I';
|
|
1796
|
+
}
|
|
1797
|
+
function orderedListStyle(value) {
|
|
1798
|
+
const type = normalizedOrderedListType(value);
|
|
1799
|
+
if ('a' === type) return 'lower-alpha';
|
|
1800
|
+
if ('A' === type) return 'upper-alpha';
|
|
1801
|
+
if ('i' === type) return 'lower-roman';
|
|
1802
|
+
if ('I' === type) return 'upper-roman';
|
|
1803
|
+
return 'decimal';
|
|
1804
|
+
}
|
|
1805
|
+
function normalizedOrderedListType(value) {
|
|
1806
|
+
return 'a' === value || 'A' === value || 'i' === value || 'I' === value ? value : null;
|
|
1807
|
+
}
|
|
1808
|
+
function normalizedNumberingStart(value) {
|
|
1809
|
+
const start = Number(value);
|
|
1810
|
+
return validNumberingStart(start) ? start : 1;
|
|
1811
|
+
}
|
|
1812
|
+
function validNumberingStart(value) {
|
|
1813
|
+
return Number.isSafeInteger(value) && value >= 1 && value <= MAX_DOCUMENT_NUMBERING_START;
|
|
1814
|
+
}
|
|
1815
|
+
const DocumentNoteReference = Node.create({
|
|
1816
|
+
name: 'documentNoteReference',
|
|
1817
|
+
inline: true,
|
|
1818
|
+
group: 'inline',
|
|
1819
|
+
atom: true,
|
|
1820
|
+
selectable: true,
|
|
1821
|
+
addCommands () {
|
|
1822
|
+
return {
|
|
1823
|
+
insertDocumentNote: (kind)=>(props)=>insertDocumentNoteCommand(props, kind)
|
|
1824
|
+
};
|
|
1825
|
+
},
|
|
1826
|
+
addAttributes () {
|
|
1827
|
+
return {
|
|
1828
|
+
id: work_document_note_nodes_hiddenAttribute(''),
|
|
1829
|
+
kind: work_document_note_nodes_hiddenAttribute('footnote'),
|
|
1830
|
+
number: work_document_note_nodes_hiddenAttribute(1)
|
|
1831
|
+
};
|
|
1832
|
+
},
|
|
1833
|
+
parseHTML () {
|
|
1834
|
+
return [
|
|
1835
|
+
{
|
|
1836
|
+
tag: 'sup[data-document-note-reference]',
|
|
1837
|
+
getAttrs: (node)=>{
|
|
1838
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
1839
|
+
return {
|
|
1840
|
+
id: node.dataset.noteId ?? '',
|
|
1841
|
+
kind: documentNoteKind(node.dataset.noteKind) ?? 'footnote',
|
|
1842
|
+
number: work_document_note_nodes_positiveInteger(node.dataset.noteNumber)
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
];
|
|
1847
|
+
},
|
|
1848
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
1849
|
+
const kind = documentNoteKind(node.attrs.kind) ?? 'footnote';
|
|
1850
|
+
const number = work_document_note_nodes_positiveInteger(node.attrs.number);
|
|
1851
|
+
return [
|
|
1852
|
+
'sup',
|
|
1853
|
+
mergeAttributes(HTMLAttributes, {
|
|
1854
|
+
'data-document-note-reference': 'true',
|
|
1855
|
+
'data-note-kind': kind,
|
|
1856
|
+
'data-note-id': 'string' == typeof node.attrs.id ? node.attrs.id : '',
|
|
1857
|
+
'data-note-number': String(number),
|
|
1858
|
+
class: 'work-document-note-reference'
|
|
1859
|
+
}),
|
|
1860
|
+
String(number)
|
|
1861
|
+
];
|
|
1862
|
+
},
|
|
1863
|
+
renderText ({ node }) {
|
|
1864
|
+
return String(work_document_note_nodes_positiveInteger(node.attrs.number));
|
|
1865
|
+
}
|
|
1866
|
+
});
|
|
1867
|
+
const DocumentNote = Node.create({
|
|
1868
|
+
name: 'documentNote',
|
|
1869
|
+
group: 'block',
|
|
1870
|
+
content: 'block+',
|
|
1871
|
+
defining: true,
|
|
1872
|
+
isolating: true,
|
|
1873
|
+
addAttributes () {
|
|
1874
|
+
return {
|
|
1875
|
+
id: work_document_note_nodes_hiddenAttribute(''),
|
|
1876
|
+
kind: work_document_note_nodes_hiddenAttribute('footnote'),
|
|
1877
|
+
number: work_document_note_nodes_hiddenAttribute(1)
|
|
1878
|
+
};
|
|
1879
|
+
},
|
|
1880
|
+
parseHTML () {
|
|
1881
|
+
return [
|
|
1882
|
+
{
|
|
1883
|
+
tag: 'aside[data-document-note]',
|
|
1884
|
+
getAttrs: (node)=>{
|
|
1885
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
1886
|
+
return {
|
|
1887
|
+
id: node.dataset.noteId ?? '',
|
|
1888
|
+
kind: documentNoteKind(node.dataset.noteKind) ?? 'footnote',
|
|
1889
|
+
number: work_document_note_nodes_positiveInteger(node.dataset.noteNumber)
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
];
|
|
1894
|
+
},
|
|
1895
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
1896
|
+
const kind = documentNoteKind(node.attrs.kind) ?? 'footnote';
|
|
1897
|
+
const number = work_document_note_nodes_positiveInteger(node.attrs.number);
|
|
1898
|
+
return [
|
|
1899
|
+
'aside',
|
|
1900
|
+
mergeAttributes(HTMLAttributes, {
|
|
1901
|
+
'data-document-note': 'true',
|
|
1902
|
+
'data-note-kind': kind,
|
|
1903
|
+
'data-note-id': 'string' == typeof node.attrs.id ? node.attrs.id : '',
|
|
1904
|
+
'data-note-number': String(number),
|
|
1905
|
+
class: 'work-document-note'
|
|
1906
|
+
}),
|
|
1907
|
+
0
|
|
1908
|
+
];
|
|
1909
|
+
}
|
|
1910
|
+
});
|
|
1911
|
+
function insertDocumentNoteCommand({ dispatch, editor, state, tr }, kind) {
|
|
1912
|
+
const section = activeDocumentSectionFromState(state);
|
|
1913
|
+
const referenceType = editor.schema.nodes.documentNoteReference;
|
|
1914
|
+
const noteType = editor.schema.nodes.documentNote;
|
|
1915
|
+
const paragraphType = editor.schema.nodes.paragraph;
|
|
1916
|
+
if (!section || !referenceType || !noteType || !paragraphType || work_document_note_nodes_selectionInsideNode(state, 'documentNote')) return false;
|
|
1917
|
+
if (!dispatch) return true;
|
|
1918
|
+
const number = nextNoteNumber(state, kind);
|
|
1919
|
+
const id = createWorkId(kind);
|
|
1920
|
+
const attributes = {
|
|
1921
|
+
id,
|
|
1922
|
+
kind,
|
|
1923
|
+
number
|
|
1924
|
+
};
|
|
1925
|
+
tr.replaceSelectionWith(referenceType.create(attributes), false);
|
|
1926
|
+
const updatedSection = tr.doc.nodeAt(section.position);
|
|
1927
|
+
if (!updatedSection || 'documentSection' !== updatedSection.type.name) return false;
|
|
1928
|
+
const insertPosition = section.position + updatedSection.nodeSize - 1;
|
|
1929
|
+
tr.insert(insertPosition, noteType.create(attributes, paragraphType.create()));
|
|
1930
|
+
tr.setSelection(TextSelection.near(tr.doc.resolve(insertPosition + 2)));
|
|
1931
|
+
tr.scrollIntoView();
|
|
1932
|
+
return true;
|
|
1933
|
+
}
|
|
1934
|
+
function nextNoteNumber(state, kind) {
|
|
1935
|
+
const ids = new Set();
|
|
1936
|
+
state.doc.descendants((node)=>{
|
|
1937
|
+
if ('documentNoteReference' !== node.type.name || node.attrs.kind !== kind) return;
|
|
1938
|
+
const id = 'string' == typeof node.attrs.id ? node.attrs.id : '';
|
|
1939
|
+
if (id) ids.add(documentNoteKey(kind, id));
|
|
1940
|
+
});
|
|
1941
|
+
return ids.size + 1;
|
|
1942
|
+
}
|
|
1943
|
+
function work_document_note_nodes_selectionInsideNode(state, nodeName) {
|
|
1944
|
+
for(let depth = state.selection.$from.depth; depth > 0; depth -= 1)if (state.selection.$from.node(depth).type.name === nodeName) return true;
|
|
1945
|
+
return false;
|
|
1946
|
+
}
|
|
1947
|
+
function work_document_note_nodes_hiddenAttribute(defaultValue) {
|
|
1948
|
+
return {
|
|
1949
|
+
default: defaultValue,
|
|
1950
|
+
rendered: false
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
function work_document_note_nodes_positiveInteger(value) {
|
|
1954
|
+
const number = Number(value);
|
|
1955
|
+
return Number.isSafeInteger(number) && number > 0 ? number : 1;
|
|
1956
|
+
}
|
|
1957
|
+
const DocumentPageBreak = Node.create({
|
|
1958
|
+
name: 'pageBreak',
|
|
1959
|
+
group: 'block',
|
|
1960
|
+
atom: true,
|
|
1961
|
+
selectable: true,
|
|
1962
|
+
parseHTML () {
|
|
1963
|
+
return [
|
|
1964
|
+
{
|
|
1965
|
+
tag: '[data-page-break]'
|
|
1966
|
+
}
|
|
1967
|
+
];
|
|
1968
|
+
},
|
|
1969
|
+
renderHTML ({ HTMLAttributes }) {
|
|
1970
|
+
return [
|
|
1971
|
+
'div',
|
|
1972
|
+
mergeAttributes(HTMLAttributes, {
|
|
1973
|
+
'data-page-break': 'true',
|
|
1974
|
+
class: 'work-page-break',
|
|
1975
|
+
role: 'separator',
|
|
1976
|
+
'aria-label': '分页符'
|
|
1977
|
+
})
|
|
1978
|
+
];
|
|
1979
|
+
},
|
|
1980
|
+
addKeyboardShortcuts () {
|
|
1981
|
+
return {
|
|
1982
|
+
'Mod-Enter': ()=>this.editor.chain().insertContent({
|
|
1983
|
+
type: this.name
|
|
1984
|
+
}).run()
|
|
1985
|
+
};
|
|
1986
|
+
}
|
|
1987
|
+
});
|
|
1988
|
+
const DocumentSection = Node.create({
|
|
1989
|
+
name: 'documentSection',
|
|
1990
|
+
group: 'block',
|
|
1991
|
+
content: 'block+',
|
|
1992
|
+
defining: true,
|
|
1993
|
+
isolating: true,
|
|
1994
|
+
addAttributes () {
|
|
1995
|
+
return {
|
|
1996
|
+
id: work_document_section_node_hiddenAttribute(''),
|
|
1997
|
+
pageSize: work_document_section_node_hiddenAttribute('a4'),
|
|
1998
|
+
orientation: work_document_section_node_hiddenAttribute('portrait'),
|
|
1999
|
+
marginTop: work_document_section_node_hiddenAttribute(25),
|
|
2000
|
+
marginRight: work_document_section_node_hiddenAttribute(23),
|
|
2001
|
+
marginBottom: work_document_section_node_hiddenAttribute(25),
|
|
2002
|
+
marginLeft: work_document_section_node_hiddenAttribute(23),
|
|
2003
|
+
columnCount: work_document_section_node_hiddenAttribute(1),
|
|
2004
|
+
columnSpacing: work_document_section_node_hiddenAttribute(12),
|
|
2005
|
+
columnSeparator: work_document_section_node_hiddenAttribute(false),
|
|
2006
|
+
columnLayout: work_document_section_node_hiddenAttribute(''),
|
|
2007
|
+
breakAfter: work_document_section_node_hiddenAttribute('nextPage'),
|
|
2008
|
+
headerText: work_document_section_node_hiddenAttribute(''),
|
|
2009
|
+
footerText: work_document_section_node_hiddenAttribute(''),
|
|
2010
|
+
showPageNumbers: work_document_section_node_hiddenAttribute(false),
|
|
2011
|
+
pageNumberStart: work_document_section_node_hiddenAttribute(null),
|
|
2012
|
+
pageChrome: work_document_section_node_hiddenAttribute('')
|
|
2013
|
+
};
|
|
2014
|
+
},
|
|
2015
|
+
addCommands () {
|
|
2016
|
+
return {
|
|
2017
|
+
insertDocumentSection: (breakAfter = 'nextPage')=>({ dispatch, editor, state, tr })=>{
|
|
2018
|
+
const section = activeDocumentSection(editor);
|
|
2019
|
+
if (!section || !editor.schema.nodes.documentSection || !editor.schema.nodes.paragraph) return false;
|
|
2020
|
+
return dispatch ? insertDocumentSection(editor, breakAfter, {
|
|
2021
|
+
state,
|
|
2022
|
+
tr
|
|
2023
|
+
}) : true;
|
|
2024
|
+
},
|
|
2025
|
+
mergeDocumentSectionWithPrevious: ()=>({ dispatch, editor, state, tr })=>{
|
|
2026
|
+
const section = activeDocumentSection(editor);
|
|
2027
|
+
if (!section || 0 === section.index) return false;
|
|
2028
|
+
return dispatch ? mergeDocumentSectionWithPrevious(editor, {
|
|
2029
|
+
state,
|
|
2030
|
+
tr
|
|
2031
|
+
}) : true;
|
|
2032
|
+
},
|
|
2033
|
+
updateActiveDocumentSection: (layout)=>({ dispatch, editor, state, tr })=>{
|
|
2034
|
+
if (!activeDocumentSection(editor)) return false;
|
|
2035
|
+
return dispatch ? updateActiveDocumentSection(layout, {
|
|
2036
|
+
state,
|
|
2037
|
+
tr
|
|
2038
|
+
}) : true;
|
|
2039
|
+
},
|
|
2040
|
+
updateDocumentSection: (sectionId, layout)=>({ dispatch, editor, state, tr })=>{
|
|
2041
|
+
if (!documentSectionById(editor, sectionId)) return false;
|
|
2042
|
+
return dispatch ? updateDocumentSection(sectionId, layout, {
|
|
2043
|
+
state,
|
|
2044
|
+
tr
|
|
2045
|
+
}) : true;
|
|
2046
|
+
}
|
|
2047
|
+
};
|
|
2048
|
+
},
|
|
2049
|
+
parseHTML () {
|
|
2050
|
+
return [
|
|
2051
|
+
{
|
|
2052
|
+
tag: 'section[data-document-section]',
|
|
2053
|
+
getAttrs: (node)=>{
|
|
2054
|
+
if (!(node instanceof HTMLElement)) return false;
|
|
2055
|
+
return {
|
|
2056
|
+
id: node.dataset.sectionId ?? '',
|
|
2057
|
+
pageSize: 'letter' === node.dataset.sectionPageSize ? 'letter' : 'a4',
|
|
2058
|
+
orientation: 'landscape' === node.dataset.sectionOrientation ? 'landscape' : 'portrait',
|
|
2059
|
+
marginTop: numberAttribute(node, 'sectionMarginTop', 25),
|
|
2060
|
+
marginRight: numberAttribute(node, 'sectionMarginRight', 23),
|
|
2061
|
+
marginBottom: numberAttribute(node, 'sectionMarginBottom', 25),
|
|
2062
|
+
marginLeft: numberAttribute(node, 'sectionMarginLeft', 23),
|
|
2063
|
+
columnCount: numberAttribute(node, 'sectionColumnCount', 1),
|
|
2064
|
+
columnSpacing: numberAttribute(node, 'sectionColumnSpacing', 12),
|
|
2065
|
+
columnSeparator: 'true' === node.dataset.sectionColumnSeparator,
|
|
2066
|
+
columnLayout: node.dataset.sectionColumnLayout ?? '',
|
|
2067
|
+
breakAfter: sectionBreakAttribute(node.dataset.sectionBreakAfter),
|
|
2068
|
+
headerText: node.dataset.sectionHeaderText ?? '',
|
|
2069
|
+
footerText: node.dataset.sectionFooterText ?? '',
|
|
2070
|
+
showPageNumbers: 'true' === node.dataset.sectionShowPageNumbers,
|
|
2071
|
+
pageNumberStart: nullableNumberAttribute(node, 'sectionPageNumberStart'),
|
|
2072
|
+
pageChrome: node.dataset.sectionPageChrome ?? ''
|
|
2073
|
+
};
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
];
|
|
2077
|
+
},
|
|
2078
|
+
renderHTML ({ node, HTMLAttributes }) {
|
|
2079
|
+
const layout = documentSectionLayoutFromNodeAttributes(node.attrs);
|
|
2080
|
+
const id = 'string' == typeof node.attrs.id && node.attrs.id ? node.attrs.id : 'document-section';
|
|
2081
|
+
const columns = layout.columns;
|
|
2082
|
+
const style = [
|
|
2083
|
+
`--work-document-column-count:${columns.count}`,
|
|
2084
|
+
`--work-document-column-gap:${columns.spacing}mm`,
|
|
2085
|
+
`--work-document-column-rule:${columns.separator ? '1px solid var(--a3s-line-strong)' : 'none'}`
|
|
2086
|
+
].join(';');
|
|
2087
|
+
return [
|
|
2088
|
+
'section',
|
|
2089
|
+
mergeAttributes(HTMLAttributes, documentSectionDomAttributes(layout, id), {
|
|
2090
|
+
class: 'work-document-section',
|
|
2091
|
+
style
|
|
2092
|
+
}),
|
|
2093
|
+
0
|
|
2094
|
+
];
|
|
2095
|
+
}
|
|
2096
|
+
});
|
|
2097
|
+
function work_document_section_node_hiddenAttribute(defaultValue) {
|
|
2098
|
+
return {
|
|
2099
|
+
default: defaultValue,
|
|
2100
|
+
rendered: false
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
function numberAttribute(element, name, fallback) {
|
|
2104
|
+
const value = Number(element.dataset[name]);
|
|
2105
|
+
return Number.isFinite(value) ? value : fallback;
|
|
2106
|
+
}
|
|
2107
|
+
function nullableNumberAttribute(element, name) {
|
|
2108
|
+
const source = element.dataset[name];
|
|
2109
|
+
if (!source?.trim()) return null;
|
|
2110
|
+
const value = Number(source);
|
|
2111
|
+
return Number.isFinite(value) ? value : null;
|
|
2112
|
+
}
|
|
2113
|
+
function sectionBreakAttribute(value) {
|
|
2114
|
+
if ('continuous' === value || 'evenPage' === value || 'oddPage' === value || 'nextColumn' === value) return value;
|
|
2115
|
+
return 'nextPage';
|
|
2116
|
+
}
|
|
2117
|
+
const DOCUMENT_TAB_SELECTOR = 'span[data-document-tab]';
|
|
2118
|
+
const DOCUMENT_TAB_BLOCK_SELECTOR = 'p, h1, h2, h3, h4, h5, h6';
|
|
2119
|
+
const MINIMUM_DOCUMENT_TAB_WIDTH_PX = 1;
|
|
2120
|
+
const DocumentTab = Node.create({
|
|
2121
|
+
name: 'documentTab',
|
|
2122
|
+
group: 'inline',
|
|
2123
|
+
inline: true,
|
|
2124
|
+
atom: true,
|
|
2125
|
+
selectable: false,
|
|
2126
|
+
parseHTML () {
|
|
2127
|
+
return [
|
|
2128
|
+
{
|
|
2129
|
+
tag: DOCUMENT_TAB_SELECTOR
|
|
2130
|
+
}
|
|
2131
|
+
];
|
|
2132
|
+
},
|
|
2133
|
+
renderHTML ({ HTMLAttributes }) {
|
|
2134
|
+
return [
|
|
2135
|
+
'span',
|
|
2136
|
+
mergeAttributes(HTMLAttributes, {
|
|
2137
|
+
'data-document-tab': 'true',
|
|
2138
|
+
class: 'work-document-tab',
|
|
2139
|
+
role: 'separator',
|
|
2140
|
+
'aria-label': '制表符'
|
|
2141
|
+
})
|
|
2142
|
+
];
|
|
2143
|
+
},
|
|
2144
|
+
addNodeView () {
|
|
2145
|
+
return ()=>{
|
|
2146
|
+
const dom = document.createElement('span');
|
|
2147
|
+
dom.className = 'work-document-tab';
|
|
2148
|
+
dom.dataset.documentTab = 'true';
|
|
2149
|
+
dom.setAttribute('role', 'separator');
|
|
2150
|
+
dom.setAttribute('aria-label', '制表符');
|
|
2151
|
+
dom.contentEditable = 'false';
|
|
2152
|
+
return {
|
|
2153
|
+
dom,
|
|
2154
|
+
ignoreMutation: ()=>true
|
|
2155
|
+
};
|
|
2156
|
+
};
|
|
2157
|
+
},
|
|
2158
|
+
addKeyboardShortcuts () {
|
|
2159
|
+
return {
|
|
2160
|
+
Tab: ()=>{
|
|
2161
|
+
const position = this.editor.state.selection.$from;
|
|
2162
|
+
if (selectionIsInsideTableCell(position) || selectionIsInsideListItem(position)) return false;
|
|
2163
|
+
return this.editor.chain().focus().insertContent({
|
|
2164
|
+
type: this.name
|
|
2165
|
+
}).run();
|
|
2166
|
+
}
|
|
2167
|
+
};
|
|
2168
|
+
},
|
|
2169
|
+
addProseMirrorPlugins () {
|
|
2170
|
+
return [
|
|
2171
|
+
new Plugin({
|
|
2172
|
+
view: (view)=>createDocumentTabLayoutView(view)
|
|
2173
|
+
})
|
|
2174
|
+
];
|
|
2175
|
+
}
|
|
2176
|
+
});
|
|
2177
|
+
function layoutDocumentTabs(root) {
|
|
2178
|
+
const tabs = Array.from(root.querySelectorAll(DOCUMENT_TAB_SELECTOR));
|
|
2179
|
+
for (const tab of tabs)tab.style.width = '0px';
|
|
2180
|
+
for (const tab of tabs){
|
|
2181
|
+
const block = tab.closest(DOCUMENT_TAB_BLOCK_SELECTOR);
|
|
2182
|
+
if (!block || !root.contains(block)) continue;
|
|
2183
|
+
const tabStops = normalizeDocumentTabStops(block.dataset.officeTabStops ?? '');
|
|
2184
|
+
const blockRectangle = block.getBoundingClientRect();
|
|
2185
|
+
const tabRectangle = tab.getBoundingClientRect();
|
|
2186
|
+
const layoutScale = documentElementLayoutScale(block, blockRectangle);
|
|
2187
|
+
const leftIndent = paragraphLeftIndent(block);
|
|
2188
|
+
const currentPosition = (tabRectangle.left - blockRectangle.left) / layoutScale + leftIndent;
|
|
2189
|
+
const stop = nextDocumentTabStop(tabStops, currentPosition);
|
|
2190
|
+
const offset = documentTabAlignmentOffset(tab, block, stop.alignment, layoutScale);
|
|
2191
|
+
const width = Math.max(MINIMUM_DOCUMENT_TAB_WIDTH_PX, stop.position - currentPosition - offset);
|
|
2192
|
+
tab.style.width = `${roundLayoutValue(width)}px`;
|
|
2193
|
+
tab.dataset.documentTabAlignment = stop.alignment;
|
|
2194
|
+
tab.dataset.documentTabLeader = stop.leader;
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
function nextDocumentTabStop(tabStops, currentPosition) {
|
|
2198
|
+
const current = Math.max(0, currentPosition);
|
|
2199
|
+
const custom = normalizeDocumentTabStops(tabStops).find((stop)=>stop.position > current + 0.5);
|
|
2200
|
+
const defaultPosition = (Math.floor(current / 48) + 1) * 48;
|
|
2201
|
+
if (custom && custom.position <= defaultPosition + 0.5) return custom;
|
|
2202
|
+
return {
|
|
2203
|
+
position: defaultPosition,
|
|
2204
|
+
alignment: 'left',
|
|
2205
|
+
leader: 'none'
|
|
2206
|
+
};
|
|
2207
|
+
}
|
|
2208
|
+
function createDocumentTabLayoutView(view) {
|
|
2209
|
+
let frame = null;
|
|
2210
|
+
const schedule = ()=>{
|
|
2211
|
+
if (null !== frame) cancelAnimationFrame(frame);
|
|
2212
|
+
frame = requestAnimationFrame(()=>{
|
|
2213
|
+
frame = null;
|
|
2214
|
+
if (view.dom.isConnected) layoutDocumentTabs(view.dom);
|
|
2215
|
+
});
|
|
2216
|
+
};
|
|
2217
|
+
const resizeObserver = "u" < typeof ResizeObserver ? null : new ResizeObserver(()=>schedule());
|
|
2218
|
+
resizeObserver?.observe(view.dom);
|
|
2219
|
+
window.addEventListener('resize', schedule);
|
|
2220
|
+
document.fonts?.ready.then(schedule);
|
|
2221
|
+
schedule();
|
|
2222
|
+
return {
|
|
2223
|
+
update: schedule,
|
|
2224
|
+
destroy: ()=>{
|
|
2225
|
+
if (null !== frame) cancelAnimationFrame(frame);
|
|
2226
|
+
resizeObserver?.disconnect();
|
|
2227
|
+
window.removeEventListener('resize', schedule);
|
|
2228
|
+
}
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
function selectionIsInsideTableCell(position) {
|
|
2232
|
+
for(let depth = position.depth; depth > 0; depth -= 1){
|
|
2233
|
+
const name = position.node(depth).type.name;
|
|
2234
|
+
if ('tableCell' === name || 'tableHeader' === name) return true;
|
|
2235
|
+
}
|
|
2236
|
+
return false;
|
|
2237
|
+
}
|
|
2238
|
+
function selectionIsInsideListItem(position) {
|
|
2239
|
+
for(let depth = position.depth; depth > 0; depth -= 1)if ('listItem' === position.node(depth).type.name) return true;
|
|
2240
|
+
return false;
|
|
2241
|
+
}
|
|
2242
|
+
function paragraphLeftIndent(block) {
|
|
2243
|
+
const level = Number(block.dataset.officeIndentLevel);
|
|
2244
|
+
if (Number.isFinite(level) && level > 0) return 24 * level;
|
|
2245
|
+
const pixels = Number.parseFloat(block.style.marginLeft);
|
|
2246
|
+
return Number.isFinite(pixels) ? Math.max(0, pixels) : 0;
|
|
2247
|
+
}
|
|
2248
|
+
function documentTabAlignmentOffset(tab, block, alignment, layoutScale) {
|
|
2249
|
+
if ('left' === alignment) return 0;
|
|
2250
|
+
const width = followingSegmentWidth(tab, block, 'decimal' === alignment) / layoutScale;
|
|
2251
|
+
return 'center' === alignment ? width / 2 : width;
|
|
2252
|
+
}
|
|
2253
|
+
function documentElementLayoutScale(element, rectangle) {
|
|
2254
|
+
const layoutWidth = element.offsetWidth;
|
|
2255
|
+
if (layoutWidth <= 0 || rectangle.width <= 0) return 1;
|
|
2256
|
+
const scale = rectangle.width / layoutWidth;
|
|
2257
|
+
return Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
2258
|
+
}
|
|
2259
|
+
function followingSegmentWidth(tab, block, stopAtDecimal) {
|
|
2260
|
+
const document1 = block.ownerDocument;
|
|
2261
|
+
const range = document1.createRange();
|
|
2262
|
+
range.setStartAfter(tab);
|
|
2263
|
+
const nextTab = nextTabElement(tab, block);
|
|
2264
|
+
const decimal = stopAtDecimal ? firstDecimalPosition(tab, block, nextTab) : null;
|
|
2265
|
+
if (decimal) range.setEnd(decimal.node, decimal.offset);
|
|
2266
|
+
else if (nextTab) range.setEndBefore(nextTab);
|
|
2267
|
+
else range.setEnd(block, block.childNodes.length);
|
|
2268
|
+
const rects = 'function' == typeof range.getClientRects ? Array.from(range.getClientRects()) : [];
|
|
2269
|
+
const first = rects[0];
|
|
2270
|
+
if (first && Number.isFinite(first.width)) return Math.max(0, first.width);
|
|
2271
|
+
if ('function' != typeof range.getBoundingClientRect) return 0;
|
|
2272
|
+
const rectangle = range.getBoundingClientRect();
|
|
2273
|
+
return Number.isFinite(rectangle.width) ? Math.max(0, rectangle.width) : 0;
|
|
2274
|
+
}
|
|
2275
|
+
function nextTabElement(current, block) {
|
|
2276
|
+
const tabs = Array.from(block.querySelectorAll(DOCUMENT_TAB_SELECTOR));
|
|
2277
|
+
const index = tabs.indexOf(current);
|
|
2278
|
+
return index >= 0 ? tabs[index + 1] ?? null : null;
|
|
2279
|
+
}
|
|
2280
|
+
function firstDecimalPosition(current, block, nextTab) {
|
|
2281
|
+
const walker = block.ownerDocument.createTreeWalker(block, NodeFilter.SHOW_TEXT);
|
|
2282
|
+
let afterCurrent = false;
|
|
2283
|
+
while(walker.nextNode()){
|
|
2284
|
+
const node = walker.currentNode;
|
|
2285
|
+
if (!afterCurrent) {
|
|
2286
|
+
afterCurrent = Boolean(current.compareDocumentPosition(node) & globalThis.Node.DOCUMENT_POSITION_FOLLOWING);
|
|
2287
|
+
if (!afterCurrent) continue;
|
|
2288
|
+
}
|
|
2289
|
+
if (nextTab && !(nextTab.compareDocumentPosition(node) & globalThis.Node.DOCUMENT_POSITION_PRECEDING)) break;
|
|
2290
|
+
const offset = node.data.search(/[.,,。]/);
|
|
2291
|
+
if (offset >= 0) return {
|
|
2292
|
+
node,
|
|
2293
|
+
offset
|
|
2294
|
+
};
|
|
2295
|
+
}
|
|
2296
|
+
return null;
|
|
2297
|
+
}
|
|
2298
|
+
function roundLayoutValue(value) {
|
|
2299
|
+
return Math.round(100 * value) / 100;
|
|
2300
|
+
}
|
|
2301
|
+
function documentTabLeaderLabel(leader) {
|
|
2302
|
+
if ('dot' === leader) return '点线前导符';
|
|
2303
|
+
if ('hyphen' === leader) return '短横线前导符';
|
|
2304
|
+
if ('underscore' === leader) return '下划线前导符';
|
|
2305
|
+
if ('middleDot' === leader) return '居中点前导符';
|
|
2306
|
+
return '无前导符';
|
|
2307
|
+
}
|
|
2308
|
+
const DocumentTableCommands = Extension.create({
|
|
2309
|
+
name: 'documentTableCommands',
|
|
2310
|
+
addCommands () {
|
|
2311
|
+
return {
|
|
2312
|
+
insertDocumentTable: (dimensions, options = {})=>(props)=>insertDocumentTable(props, dimensions, options)
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
});
|
|
2316
|
+
function insertDocumentTable({ chain, dispatch, editor, state }, dimensions, options) {
|
|
2317
|
+
const rows = work_document_table_commands_positiveInteger(dimensions.rows);
|
|
2318
|
+
const columns = work_document_table_commands_positiveInteger(dimensions.columns);
|
|
2319
|
+
if (null === rows || null === columns) return false;
|
|
2320
|
+
const headerRow = false !== options.headerRow;
|
|
2321
|
+
const selection = state.selection;
|
|
2322
|
+
if (!selection.empty) {
|
|
2323
|
+
const createdTable = createTable(state.schema, rows, columns, headerRow);
|
|
2324
|
+
const table = headerRow ? withRepeatingFirstRow(createdTable) : createdTable;
|
|
2325
|
+
const insertionPosition = blockInsertionPosition(selection.$to, table.type);
|
|
2326
|
+
if (null !== insertionPosition) {
|
|
2327
|
+
const transaction = state.tr.insert(insertionPosition, table);
|
|
2328
|
+
transaction.setSelection(TextSelection.near(transaction.doc.resolve(insertionPosition + 1))).scrollIntoView();
|
|
2329
|
+
dispatch?.(transaction);
|
|
2330
|
+
if (dispatch && false !== options.restoreFocus) editor.commands.focus();
|
|
2331
|
+
return true;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
let commandChain = chain();
|
|
2335
|
+
if (false !== options.restoreFocus) commandChain = commandChain.focus();
|
|
2336
|
+
if (!selection.empty) commandChain = commandChain.setTextSelection(selection.to);
|
|
2337
|
+
commandChain = commandChain.insertTable({
|
|
2338
|
+
rows,
|
|
2339
|
+
cols: columns,
|
|
2340
|
+
withHeaderRow: headerRow
|
|
2341
|
+
});
|
|
2342
|
+
if (headerRow) commandChain = commandChain.updateAttributes('tableRow', {
|
|
2343
|
+
repeatHeader: true
|
|
2344
|
+
});
|
|
2345
|
+
return commandChain.run();
|
|
2346
|
+
}
|
|
2347
|
+
function work_document_table_commands_positiveInteger(value) {
|
|
2348
|
+
if (!Number.isSafeInteger(value) || value < 1) return null;
|
|
2349
|
+
return value;
|
|
2350
|
+
}
|
|
2351
|
+
function blockInsertionPosition(position, tableType) {
|
|
2352
|
+
for(let depth = position.depth; depth > 0; depth -= 1){
|
|
2353
|
+
const parentDepth = depth - 1;
|
|
2354
|
+
const parent = position.node(parentDepth);
|
|
2355
|
+
const index = position.indexAfter(parentDepth);
|
|
2356
|
+
if (parent.canReplaceWith(index, index, tableType)) return position.after(depth);
|
|
2357
|
+
}
|
|
2358
|
+
return null;
|
|
2359
|
+
}
|
|
2360
|
+
function withRepeatingFirstRow(table) {
|
|
2361
|
+
const firstRow = table.firstChild;
|
|
2362
|
+
if (!firstRow) return table;
|
|
2363
|
+
const repeatedRow = firstRow.type.create({
|
|
2364
|
+
...firstRow.attrs,
|
|
2365
|
+
repeatHeader: true
|
|
2366
|
+
}, firstRow.content, firstRow.marks);
|
|
2367
|
+
return table.copy(table.content.replaceChild(0, repeatedRow));
|
|
2368
|
+
}
|
|
2369
|
+
function createWorkDocumentExtensions(options = {}) {
|
|
2370
|
+
const changeExtension = DocumentChange.configure({
|
|
2371
|
+
...options.isTracking ? {
|
|
2372
|
+
isTracking: options.isTracking
|
|
2373
|
+
} : {},
|
|
2374
|
+
...options.createChange ? {
|
|
2375
|
+
createChange: options.createChange
|
|
2376
|
+
} : {},
|
|
2377
|
+
...options.onTrackingChange ? {
|
|
2378
|
+
onTrackingChange: options.onTrackingChange
|
|
2379
|
+
} : {}
|
|
2380
|
+
});
|
|
2381
|
+
const citationExtension = DocumentCitation.configure({
|
|
2382
|
+
...options.getContent ? {
|
|
2383
|
+
getContent: options.getContent
|
|
2384
|
+
} : {},
|
|
2385
|
+
...options.onContentChange ? {
|
|
2386
|
+
onContentChange: options.onContentChange
|
|
2387
|
+
} : {}
|
|
2388
|
+
});
|
|
2389
|
+
const commentExtension = DocumentComment.configure({
|
|
2390
|
+
...options.getContent ? {
|
|
2391
|
+
getContent: options.getContent
|
|
2392
|
+
} : {},
|
|
2393
|
+
...options.onContentChange ? {
|
|
2394
|
+
onContentChange: options.onContentChange
|
|
2395
|
+
} : {}
|
|
2396
|
+
});
|
|
2397
|
+
return [
|
|
2398
|
+
starter_kit.configure({
|
|
2399
|
+
link: {
|
|
2400
|
+
autolink: true,
|
|
2401
|
+
defaultProtocol: 'https',
|
|
2402
|
+
openOnClick: false
|
|
2403
|
+
},
|
|
2404
|
+
underline: false,
|
|
2405
|
+
bulletList: false,
|
|
2406
|
+
orderedList: false,
|
|
2407
|
+
trailingNode: {
|
|
2408
|
+
notAfter: [
|
|
2409
|
+
'documentSection'
|
|
2410
|
+
]
|
|
2411
|
+
}
|
|
2412
|
+
}),
|
|
2413
|
+
DocumentBulletList,
|
|
2414
|
+
DocumentOrderedList,
|
|
2415
|
+
DocumentListCommands,
|
|
2416
|
+
DocumentSection,
|
|
2417
|
+
DocumentCaption,
|
|
2418
|
+
DocumentCrossReference,
|
|
2419
|
+
citationExtension,
|
|
2420
|
+
DocumentBibliography,
|
|
2421
|
+
DocumentField,
|
|
2422
|
+
commentExtension,
|
|
2423
|
+
DocumentNoteReference,
|
|
2424
|
+
DocumentNote,
|
|
2425
|
+
extension_underline,
|
|
2426
|
+
DocumentSubscript,
|
|
2427
|
+
DocumentSuperscript,
|
|
2428
|
+
DocumentImage.configure({
|
|
2429
|
+
allowBase64: true,
|
|
2430
|
+
resize: {
|
|
2431
|
+
enabled: true,
|
|
2432
|
+
alwaysPreserveAspectRatio: true,
|
|
2433
|
+
minWidth: 60,
|
|
2434
|
+
minHeight: 40
|
|
2435
|
+
}
|
|
2436
|
+
}),
|
|
2437
|
+
TableKit.configure({
|
|
2438
|
+
table: false,
|
|
2439
|
+
tableCell: false,
|
|
2440
|
+
tableHeader: false,
|
|
2441
|
+
tableRow: false
|
|
2442
|
+
}),
|
|
2443
|
+
DocumentTable,
|
|
2444
|
+
DocumentTableCell,
|
|
2445
|
+
DocumentTableHeader,
|
|
2446
|
+
DocumentTableRow,
|
|
2447
|
+
DocumentTableCommands,
|
|
2448
|
+
DocumentTableFormatting,
|
|
2449
|
+
DocumentTableSizing,
|
|
2450
|
+
TextStyle,
|
|
2451
|
+
font_family,
|
|
2452
|
+
font_size,
|
|
2453
|
+
extension_color,
|
|
2454
|
+
extension_highlight.configure({
|
|
2455
|
+
multicolor: true
|
|
2456
|
+
}),
|
|
2457
|
+
extension_text_align.configure({
|
|
2458
|
+
types: [
|
|
2459
|
+
'heading',
|
|
2460
|
+
'paragraph'
|
|
2461
|
+
]
|
|
2462
|
+
}),
|
|
2463
|
+
DocumentParagraphFormatting,
|
|
2464
|
+
DocumentParagraphTabStops,
|
|
2465
|
+
DocumentTab,
|
|
2466
|
+
DocumentPageBreak,
|
|
2467
|
+
changeExtension
|
|
2468
|
+
];
|
|
2469
|
+
}
|
|
2470
|
+
export { DocumentSubscript, DocumentSuperscript, MAX_DOCUMENT_NUMBERING_START, activeDocumentSection, canInsertDocumentComment, collectDocumentChanges, collectDocumentCommentAnchors, createWorkDocumentExtensions, documentBulletListStyle, documentCitationCount, documentCommentDraftRange, documentCommentViews, documentOrderedListState, documentSectionById, documentTabLeaderLabel, editorDocumentCaptionTargets, retainAnchoredDocumentComments };
|